labcomm2014_decoder.c 22.6 KB
Newer Older
Anders Blomdell's avatar
Anders Blomdell committed
1
/*
2
  labcomm2014_decoder.c -- runtime for handling decoding of labcomm2014 samples.
Anders Blomdell's avatar
Anders Blomdell committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

  Copyright 2006-2013 Anders Blomdell <anders.blomdell@control.lth.se>

  This file is part of LabComm.

  LabComm is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  LabComm 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
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
21
#define CURRENT_VERSION "LabComm2014"
Anders Blomdell's avatar
Anders Blomdell committed
22
23

#include <errno.h>
24
25
26
27
#include "labcomm2014.h"
#include "labcomm2014_private.h"
#include "labcomm2014_ioctl.h"
#include "labcomm2014_dynamic_buffer_writer.h"
Anders Blomdell's avatar
Anders Blomdell committed
28

29
30
31
32
33
34
35
36
37
38
39
40
#ifdef DEBUG
#define DEBUG_FPRINTF(str, ...) fprintf(str, ##__VA_ARGS__)
#else
#define DEBUG_FPRINTF(str, ...)
#endif

#ifdef DECODER_DEBUG
#define DECODER_DEBUG_FPRINTF(str, ...) fprintf(str, ##__VA_ARGS__) 
#else
#define DECODER_DEBUG_FPRINTF(str, ...)
#endif

Anders Blomdell's avatar
Anders Blomdell committed
41
42
struct sample_entry {
  int remote_index;
43
44
45
  const struct labcomm2014_signature *signature;
  labcomm2014_decoder_function decode;
  labcomm2014_handler_function handler;
Anders Blomdell's avatar
Anders Blomdell committed
46
47
48
  void *context;
};

49
50
struct decoder {
  struct labcomm2014_decoder decoder;
Anders Blomdell's avatar
Anders Blomdell committed
51
52
  LABCOMM_SIGNATURE_ARRAY_DEF(local, struct sample_entry);
  LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local, int);
53
  LABCOMM_SIGNATURE_ARRAY_DEF(local_ref, const struct labcomm2014_signature *);
54
  LABCOMM_SIGNATURE_ARRAY_DEF(remote_to_local_ref, int);
Anders Blomdell's avatar
Anders Blomdell committed
55
56
};

57
58
static int handle_sample_def(struct labcomm2014_decoder *d, int remote_index,
                             const struct labcomm2014_signature *signature)
Anders Blomdell's avatar
Anders Blomdell committed
59
{
60
  struct decoder *id = d->context;
Anders Blomdell's avatar
Anders Blomdell committed
61
  int result;
62
  int i;
63
  const struct labcomm2014_signature *local_signature = NULL;
64
65
  int local_index = 0;

66
  labcomm2014_scheduler_data_lock(d->scheduler);
67
  LABCOMM_SIGNATURE_ARRAY_FOREACH(id->local, struct sample_entry, i) {
68
69
70
71
72
    struct sample_entry *s;
    int *remote_to_local;

    result = -ENOENT;
    s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
73
                                    id->local, struct sample_entry, i);
74
75
76
77
78
79
80
81
82
    if (s->signature &&
        s->signature->size == signature->size &&
        strcmp(s->signature->name, signature->name) == 0 &&
        memcmp((void*)s->signature->signature, (void*)signature->signature,
	       signature->size) == 0) {
      s->remote_index = remote_index;
      local_signature = s->signature;
      local_index = i;
      remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
83
                                                    id->remote_to_local, int,
84
85
86
87
88
89
                                                    remote_index);
      *remote_to_local = i;
      result = remote_index;
      break;
    }
  }
90
  labcomm2014_scheduler_data_unlock(d->scheduler);
91
  if (local_signature) {
92
    labcomm2014_reader_start(d->reader, d->reader->action_context,
93
94
                         local_index, remote_index, local_signature,
                         NULL);
95
    labcomm2014_reader_end(d->reader, d->reader->action_context);
96
97
98
99
  }
  return result;
}

100
101
static int handle_sample_ref(struct labcomm2014_decoder *d, int remote_index,
                             const struct labcomm2014_signature *signature)
102
{
103
  struct decoder *id = d->context;
104
105
106
  int result;
  int i;

107
  labcomm2014_scheduler_data_lock(d->scheduler);
108
109
  LABCOMM_SIGNATURE_ARRAY_FOREACH(id->local_ref,
                                  const struct labcomm2014_signature *, i) {
110
    const struct labcomm2014_signature *s;
111
112
113
    int *remote_to_local_ref;

    result = -ENOENT;
114
    s = LABCOMM_SIGNATURE_ARRAY_GET(id->local_ref, const struct labcomm2014_signature *, i, 0);
115
116
117
118
119
120
    if (s &&
        s->signature &&
        s->size == signature->size &&
        strcmp(s->name, signature->name) == 0 &&
        memcmp((void*)s->signature, (void*)signature->signature, signature->size) == 0) {
      remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
121
122
                                                        id->remote_to_local_ref,
                                                        int,
123
124
125
126
127
128
                                                        remote_index);
      *remote_to_local_ref = i;
      result = remote_index;
      break;
    }
  }
129
  labcomm2014_scheduler_data_unlock(d->scheduler);
130
131
132
  return result;
}

133
static int decoder_skip(struct labcomm2014_decoder *d, int len, int tag)
134
135
{
  int i;
136
  DECODER_DEBUG_FPRINTF(stdout, "got tag 0x%x, skipping %d bytes\n", tag, len);
137
  for(i = 0; i <len; i++){
138
    DECODER_DEBUG_FPRINTF(stderr, ".");
139
    labcomm2014_read_byte(d->reader);
140
    if (d->reader->error < 0) {
141
      DECODER_DEBUG_FPRINTF(stderr, "\nerror while skipping: %d\n",  d->reader->error);
142
143
144
      return d->reader->error;
    }
  }
145
  DECODER_DEBUG_FPRINTF(stderr, "\n");
146
147
148
  return tag;
}

149
static int decode_sample_def_or_ref(struct labcomm2014_decoder *d, int kind)
150
151
{
  int result;
152
  struct labcomm2014_signature signature;
153
154
  int i, remote_index;

155
  remote_index = labcomm2014_read_packed32(d->reader);
Anders Blomdell's avatar
Anders Blomdell committed
156
157
158
159
  if (d->reader->error < 0) {
    result = d->reader->error;
    goto out;
  }
160
161
162
163

   int numInts = labcomm2014_read_byte(d->reader);

   if(numInts != 1) {
164
       printf("WARNING! #intentions %d != 1, this will probably crash\n", numInts);
165
166
167
168
169
170
   }
  //XXX temporary kludge for intentions
  //assume only one intention: the name
  
   labcomm2014_read_packed32(d->reader); // assume the empty key (i.e., name)

171
  signature.name = labcomm2014_read_string(d->reader);
Anders Blomdell's avatar
Anders Blomdell committed
172
173
174
  if (d->reader->error < 0) {
    result = d->reader->error;
    goto out;
Anders Blomdell's avatar
Anders Blomdell committed
175
  }
176
  signature.size = labcomm2014_read_packed32(d->reader);
Anders Blomdell's avatar
Anders Blomdell committed
177
178
  if (d->reader->error < 0) {
    result = d->reader->error;
Anders Blomdell's avatar
Anders Blomdell committed
179
180
    goto free_signature_name;
  }
181
  signature.signature = labcomm2014_memory_alloc(d->memory, 1,  signature.size);
Anders Blomdell's avatar
Anders Blomdell committed
182
183
  if (d->reader->error < 0) {
    result = d->reader->error;
Anders Blomdell's avatar
Anders Blomdell committed
184
185
    goto free_signature_name;
  }
Anders Blomdell's avatar
Anders Blomdell committed
186
  for (i = 0 ; i < signature.size ; i++) {
187
    signature.signature[i] = labcomm2014_read_byte(d->reader);
Anders Blomdell's avatar
Anders Blomdell committed
188
189
190
191
192
    if (d->reader->error < 0) {
      result = d->reader->error;
      goto free_signature_signature;
    }
  }
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  switch (kind) {
    case LABCOMM_SAMPLE_DEF: {
      result = handle_sample_def(d, remote_index, &signature);
      break;
    } 
    case LABCOMM_SAMPLE_REF: {
      result = handle_sample_ref(d, remote_index, &signature);
      if (result == -ENOENT) {
        /* Dummy value to silently continue */
        result = LABCOMM_SAMPLE_REF;
      }
      break;
    } 
    default:
      result = -EINVAL;
Anders Blomdell's avatar
Anders Blomdell committed
208
209
  }
free_signature_signature:
210
  labcomm2014_memory_free(d->memory, 1,  signature.signature);
Anders Blomdell's avatar
Anders Blomdell committed
211
free_signature_name:
212
  labcomm2014_memory_free(d->memory, 0, signature.name);
Anders Blomdell's avatar
Anders Blomdell committed
213
out:
Anders Blomdell's avatar
Anders Blomdell committed
214
215
216
217
  return result;
}

struct call_handler_context {
218
  struct labcomm2014_reader *reader;
Anders Blomdell's avatar
Anders Blomdell committed
219
220
  int local_index;
  int remote_index;
221
222
  const struct labcomm2014_signature *signature;
  labcomm2014_handler_function handler;
Anders Blomdell's avatar
Anders Blomdell committed
223
224
225
226
227
228
229
  void *context;
};

static void call_handler(void *value, void *context)
{
  struct call_handler_context *wrap = context;

230
  if (wrap->reader->error >= 0) {
231
    labcomm2014_reader_start(wrap->reader, wrap->reader->action_context,
232
233
234
			 wrap->local_index, wrap->remote_index, wrap->signature,
			 value);
    wrap->handler(value, wrap->context);
235
    labcomm2014_reader_end(wrap->reader, wrap->reader->action_context);
236
  }
Anders Blomdell's avatar
Anders Blomdell committed
237
238
}

239
static void reader_alloc(struct labcomm2014_decoder *d)
Anders Blomdell's avatar
Anders Blomdell committed
240
{
241
242
  if (!d->reader_allocated) {
    d->reader_allocated = 1;
243
    labcomm2014_reader_alloc(d->reader, d->reader->action_context);
Anders Blomdell's avatar
Anders Blomdell committed
244
245
246
  }
}

247
248
249
/* d        - decoder to read from
   registry - decoder to lookup signatures (registry != d only if
                nesting decoders, e.g., when decoding pragma)
250
   len      - length of the labcomm2014 packet )
251
*/
252
253
static int decode_pragma(struct labcomm2014_decoder *d,
		         struct labcomm2014_decoder *registry,
254
255
256
257
		         int len)
{
  char *pragma_type;
  int result;
258
  pragma_type = labcomm2014_read_string(d->reader);
259
260
261
262
  if (d->reader->error < 0) {
    result = d->reader->error;
    goto out;
  }
263
  int bytes = labcomm2014_size_string(pragma_type);
264
265
266
267
268
269
  int psize = len-bytes;
  result = decoder_skip(d, psize, LABCOMM_PRAGMA);
out:
  return result;
}

270
static labcomm2014_decoder_function lookup_h(struct labcomm2014_decoder *d,
271
272
273
274
		                         struct call_handler_context *wrap,
		                         int remote_index,
					 int **local_index)
{
275
  struct decoder *id = d->context;
276
277
  labcomm2014_decoder_function do_decode = NULL;
  labcomm2014_scheduler_data_lock(d->scheduler);
278
  *local_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
279
280
                                             id->remote_to_local, int,
                                             remote_index);
281
282
283
284
  if (**local_index != 0) {
    struct sample_entry *entry;

    entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
285
286
                                        id->local, struct sample_entry,
                                        **local_index);
287
288
289
290
291
292
    wrap->local_index = **local_index;
    wrap->signature = entry->signature;
    wrap->handler = entry->handler;
    wrap->context = entry->context;
    do_decode = entry->decode;
  }
293
  labcomm2014_scheduler_data_unlock(d->scheduler);
294
295
296
297
298
299
300
  return do_decode;
}
/* d            - decoder to read from
   registry     - decoder to lookup signatures (registry != d only if
                    nesting decoders, e.g., when decoding pragma)
   remote_index -  received type index )
*/
301
302
static int decode_and_handle(struct labcomm2014_decoder *d,
		             struct labcomm2014_decoder *registry,
303
304
305
306
307
308
309
310
311
312
313
		             int remote_index)
{
  int result;
  int *local_index;
  struct call_handler_context wrap = {
    .reader = d->reader,
    .remote_index = remote_index,
    .signature = NULL,
    .handler = NULL,
    .context = NULL,
  };
314
  labcomm2014_decoder_function do_decode = lookup_h(registry, &wrap, remote_index, &local_index);
315
316
317
318
319
320
321
322
323
324
325
  result = *local_index;
  if (do_decode) {
    do_decode(d->reader, call_handler, &wrap);
    if (d->reader->error < 0) {
      result = d->reader->error;
    }
  } else {
    result = -ENOENT;
  }
  return result;
}
326

327
int labcomm2014_decoder_decode_one(struct labcomm2014_decoder *d)
328
329
330
331
332
{
  return d->decode_one(d);
}

static int do_decode_one(struct labcomm2014_decoder *d)
Anders Blomdell's avatar
Anders Blomdell committed
333
{
334
  int result, remote_index, length;
Anders Blomdell's avatar
Anders Blomdell committed
335

336
  reader_alloc(d);
337
  remote_index = labcomm2014_read_packed32(d->reader);
Anders Blomdell's avatar
Anders Blomdell committed
338
339
340
341
  if (d->reader->error < 0) {
    result = d->reader->error;
    goto out;
  }
342
  length = labcomm2014_read_packed32(d->reader);
343
344
345
346
  if (d->reader->error < 0) {
    result = d->reader->error;
    goto out;
  }
347
  if (remote_index == LABCOMM_VERSION) {
348
    char *version = labcomm2014_read_string(d->reader);
349
350
351
352
353
354
355
356
357
358
    if (d->reader->error < 0) {
      result = d->reader->error;
      goto out;
    }
    if (strcmp(version, CURRENT_VERSION) == 0) {
      result = LABCOMM_VERSION;
      d->version_ok = 1;
    } else {
      result = -ECONNRESET;
    }  
359
    labcomm2014_memory_free(d->memory, 1,  version);
360
  } else if (! d->version_ok) {
361
    DEBUG_FPRINTF(stderr, "No VERSION %d %d\n", remote_index, length);
362
    result = -ECONNRESET;
363
364
365
366
  } else if (remote_index == LABCOMM_SAMPLE_DEF) {
    result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_DEF); 
  } else if (remote_index == LABCOMM_SAMPLE_REF) {
    result = decode_sample_def_or_ref(d, LABCOMM_SAMPLE_REF); 
367
  } else if (remote_index == LABCOMM_TYPE_DEF) {
368
    result = decode_and_handle(d, d, remote_index);
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
369
    if(result == -ENOENT) { 
370
        //No handler for type_defs, skip
Sven Gestegård Robertz's avatar
Sven Gestegård Robertz committed
371
        result = decoder_skip(d, length, remote_index);
372
    }
373
  } else if (remote_index == LABCOMM_TYPE_BINDING) {
374
375
376
377
378
    result = decode_and_handle(d, d, remote_index);
    if(result == -ENOENT) { 
        //No handler for type_bindings, skip
        result = decoder_skip(d, length, remote_index);
    }
379
380
  } else if (remote_index == LABCOMM_PRAGMA) {
    result = decode_pragma(d, d, length);
381
  } else if (remote_index < LABCOMM_USER) {
382
    DECODER_DEBUG_FPRINTF(stderr, "SKIP %d %d\n", remote_index, length);
383
    result = decoder_skip(d, length, remote_index);
Anders Blomdell's avatar
Anders Blomdell committed
384
  } else {
385
    result = decode_and_handle(d, d, remote_index);
Anders Blomdell's avatar
Anders Blomdell committed
386
  }
387
out:   
Anders Blomdell's avatar
Anders Blomdell committed
388
389
390
  return result;
}

391
void labcomm2014_decoder_run(struct labcomm2014_decoder *d)
Anders Blomdell's avatar
Anders Blomdell committed
392
{
393
  while (labcomm2014_decoder_decode_one(d) > 0) {
Anders Blomdell's avatar
Anders Blomdell committed
394
395
396
  }
}

397
int labcomm2014_decoder_ioctl(struct labcomm2014_decoder *d, 
398
399
                              uint32_t action,
                              ...)
Anders Blomdell's avatar
Anders Blomdell committed
400
401
402
403
404
{
  int result;  
  va_list va;
    
  va_start(va, action);
405
  result = d->ioctl(d, NULL, action, va);
Anders Blomdell's avatar
Anders Blomdell committed
406
407
408
409
  va_end(va);
  return result;
}

410
411
412
int labcomm2014_decoder_sample_ref_register(
  struct labcomm2014_decoder *d,
  const struct labcomm2014_signature *signature)
413
414
415
416
417
418
419
{
  return d->ref_register(d, signature);
}

static int do_ref_register(
  struct labcomm2014_decoder *d,
  const struct labcomm2014_signature *signature)
420
{
421
  struct decoder *id = d->context;
422
  int local_index, *remote_to_local_ref;
423
  const struct labcomm2014_signature **s;
424

425
  local_index = labcomm2014_get_local_index(signature);
426
  if (local_index <= 0) { goto out; }
427
  labcomm2014_scheduler_data_lock(d->scheduler);
428
  s = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
429
                                  id->local_ref, 
430
                                  const struct labcomm2014_signature*, local_index);
431
432
433
434
  if (s == NULL) { local_index = -ENOMEM; goto unlock; };
  if (*s) { goto unlock; }
  *s = signature;	
  remote_to_local_ref = LABCOMM_SIGNATURE_ARRAY_REF(d->memory, 
435
                                                    id->remote_to_local_ref, 
436
437
438
                                                    int, local_index);
  *remote_to_local_ref = 0;
unlock:
439
  labcomm2014_scheduler_data_unlock(d->scheduler);
440
441
442
443
out:
  return local_index;
}

444
445
446
static int do_ioctl(struct labcomm2014_decoder *d, 
                    const struct labcomm2014_signature *signature,
                    uint32_t action, va_list va)
Anders Blomdell's avatar
Anders Blomdell committed
447
{
448
  struct decoder *id = d->context;
Anders Blomdell's avatar
Anders Blomdell committed
449
450
451
  int result;
  int local_index, remote_index;

452
  local_index = labcomm2014_get_local_index(signature);
453
454
455
456
457
458
459
460
461
462
  if (local_index == 0) {
    remote_index = 0;
  } else {
    labcomm2014_scheduler_data_lock(d->scheduler);
    remote_index = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
                                               id->local,
                                               struct sample_entry,
                                               local_index)->remote_index;
    labcomm2014_scheduler_data_unlock(d->scheduler);
  }
463
  result = labcomm2014_reader_ioctl(d->reader, d->reader->action_context,
464
465
                                    local_index, remote_index, 
                                    signature, action, va);
Anders Blomdell's avatar
Anders Blomdell committed
466
467
468
  return result;
}

469
#ifndef LABCOMM_NO_TYPEDECL
470
//// Code for allowing user code to handle type_defs 
471
472
//// (should perhaps be moved to another file)

473
static void decode_raw_type_def(
474
  struct labcomm2014_reader *r,
475
  void (*handle)(
476
    struct labcomm2014_raw_type_def *v,
477
478
479
480
481
    void *context
  ),
  void *context
)
{
482
483
  struct labcomm2014_raw_type_def v;
  v.index = labcomm2014_read_packed32(r);
484
  if (r->error < 0) { goto out; }
485
486
487
488
489
490
491
492
493
494
  {
  int numInts = labcomm2014_read_byte(r);

  if(numInts != 1) {
    printf("WARNING! #intentions %d != 1, this will probably crash\n", numInts);
  }
  //XXX temporary kludge for intentions
  //assume only one intention: the name
  labcomm2014_read_packed32(r); // assume the empty key (i.e., name)
  }
495
  v.name  = labcomm2014_read_string(r);
496
  if (r->error < 0) { goto free_name; }
497
  v.length = labcomm2014_read_packed32(r);
498
  if (r->error < 0) { goto free_name; }
499
  int i;
500
  v.signature_data = labcomm2014_memory_alloc(r->memory, 1, v.length);
501
502
  if(v.signature_data) {
    for(i=0; i<v.length; i++) {
503
      v.signature_data[i] = labcomm2014_read_byte(r);
504
      if (r->error < 0) { goto free_sig; }
505
506
507
508
    }  
    handle(&v, context);
    }
free_sig:
509
  labcomm2014_memory_free(r->memory, 1, v.signature_data);
510
free_name:
511
  labcomm2014_memory_free(r->memory, 1, v.name);
512
513
514
out:
  return;
}
515
516
int labcomm2014_decoder_register_labcomm2014_type_def(
  struct labcomm2014_decoder *d,
517
  void (*handler)(
518
    struct labcomm2014_raw_type_def *v,
519
520
521
522
523
    void *context
  ),
  void *context
)
{
524
  struct decoder *id = d->context;
525
526
527
528
  int tag = LABCOMM_TYPE_DEF;
  struct sample_entry *entry;
  int *remote_to_local;
 
529
  labcomm2014_scheduler_data_lock(d->scheduler);
530
  entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
531
				      id->local, struct sample_entry,
532
533
				      tag);
  if (entry == NULL) { tag = -ENOMEM; goto unlock; }
534
  entry->remote_index = tag;
535
  entry->signature = NULL;
536
537
  entry->decode = (labcomm2014_decoder_function) decode_raw_type_def;
  entry->handler =(labcomm2014_handler_function) handler;
538
539
540
  entry->context = context;

  remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
541
542
                                                id->remote_to_local, int,
                                                tag);
543
544
  *remote_to_local = tag;
unlock:
545
  labcomm2014_scheduler_data_unlock(d->scheduler);
546
547
548
549

  return tag;
}

550
551

static void decode_type_binding(
552
  struct labcomm2014_reader *r,
553
  void (*handle)(
554
    struct labcomm2014_type_binding *v,
555
556
557
558
559
    void *context
  ),
  void *context
)
{
560
561
  struct labcomm2014_type_binding v;
  v.sample_index = labcomm2014_read_packed32(r);
562
  if (r->error < 0) { goto out; }
563
  v.type_index = labcomm2014_read_packed32(r);
564
565
566
567
568
569
  if (r->error < 0) { goto out; }
  handle(&v, context);
out:
  return;
}

570
571
int labcomm2014_decoder_register_labcomm2014_type_binding(
  struct labcomm2014_decoder *d,
572
  void (*handler)(
573
    struct labcomm2014_type_binding *v,
574
575
576
577
578
    void *context
  ),
  void *context
)
{
579
  struct decoder *id = d->context;
580
581
582
583
  int tag = LABCOMM_TYPE_BINDING;
  struct sample_entry *entry;
  int *remote_to_local;
 
584
  labcomm2014_scheduler_data_lock(d->scheduler);
585
  entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
586
				      id->local, struct sample_entry,
587
588
589
590
				      tag);
  if (entry == NULL) { tag = -ENOMEM; goto unlock; }
  entry->remote_index = tag;
  entry->signature = NULL;
591
592
  entry->decode = (labcomm2014_decoder_function) decode_type_binding;
  entry->handler =(labcomm2014_handler_function) handler;
593
594
595
  entry->context = context;

  remote_to_local = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
596
597
                                                id->remote_to_local, int,
                                                tag);
598
599
  *remote_to_local = tag;
unlock:
600
  labcomm2014_scheduler_data_unlock(d->scheduler);
601
602
603
604

  return tag;
}

605
//// End type_def handling
606
607
#endif

608
static int do_register_sample(
609
610
611
612
  struct labcomm2014_decoder *d,
  const struct labcomm2014_signature *signature,
  labcomm2014_decoder_function decode, 
  labcomm2014_handler_function handler,
Anders Blomdell's avatar
Anders Blomdell committed
613
614
  void *context)
{
615
  struct decoder *id = d->context;
Anders Blomdell's avatar
Anders Blomdell committed
616
617
618
  int local_index;
  struct sample_entry *entry;
 
619
  reader_alloc(d);
620
  local_index = labcomm2014_get_local_index(signature);
Anders Blomdell's avatar
Anders Blomdell committed
621
  if (local_index <= 0) { goto out; }
622
  labcomm2014_reader_start(d->reader, d->reader->action_context,
Anders Blomdell's avatar
Anders Blomdell committed
623
624
		       local_index, 0, signature,
		       NULL);
625
  labcomm2014_reader_end(d->reader, d->reader->action_context);
Anders Blomdell's avatar
Anders Blomdell committed
626

627
  labcomm2014_scheduler_data_lock(d->scheduler);
Anders Blomdell's avatar
Anders Blomdell committed
628
  entry = LABCOMM_SIGNATURE_ARRAY_REF(d->memory,
629
				      id->local, struct sample_entry,
Anders Blomdell's avatar
Anders Blomdell committed
630
631
632
633
634
635
636
637
				      local_index);
  if (entry == NULL) { local_index = -ENOMEM; goto unlock; }
  entry->remote_index = 0;
  entry->signature = signature;
  entry->decode = decode;
  entry->handler = handler;
  entry->context = context;
unlock:
638
  labcomm2014_scheduler_data_unlock(d->scheduler);
Anders Blomdell's avatar
Anders Blomdell committed
639
640
641
642
out:
  return local_index;
}

643
static const struct labcomm2014_sample_ref *do_index_to_sample_ref(
644
  struct labcomm2014_decoder *d, int index)
645
{
646
  const struct labcomm2014_signature *result = 0;
647
  struct decoder *id = d->context;
648
649
  int local_index;

650
  labcomm2014_scheduler_data_lock(d->scheduler);
651
  local_index = LABCOMM_SIGNATURE_ARRAY_GET(id->remote_to_local_ref, 
652
653
                                            int, index, 0);
  if (local_index) {
654
    result = LABCOMM_SIGNATURE_ARRAY_GET(id->local_ref, 
655
                                         const struct labcomm2014_signature*, 
656
657
                                         local_index, 0);
  }
658
  labcomm2014_scheduler_data_unlock(d->scheduler);
659
  return labcomm2014_signature_to_sample_ref(result);
660
}
661

662
static const struct labcomm2014_sample_ref *do_ref_get(
Anders Blomdell's avatar
Anders Blomdell committed
663
664
665
  struct labcomm2014_decoder *d,
  const struct labcomm2014_signature *signature)
{
666
  return (const struct labcomm2014_sample_ref *) signature;
Anders Blomdell's avatar
Anders Blomdell committed
667
668
}

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
static void do_free(struct labcomm2014_decoder* d)
{
  struct decoder *id = d->context;
  struct labcomm2014_memory *memory = d->memory;

  labcomm2014_reader_free(d->reader, d->reader->action_context);
  LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->local, struct sample_entry);
  LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->remote_to_local, int);
  LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->local_ref, 
                               const struct labcomm2014_signature*);
  LABCOMM_SIGNATURE_ARRAY_FREE(memory, id->remote_to_local_ref, int);
  labcomm2014_memory_free(memory, 0, id);
}

void labcomm2014_decoder_free(struct labcomm2014_decoder* d)
{
  d->free(d);
}

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
struct labcomm2014_decoder *labcomm2014_decoder_new(
  struct labcomm2014_reader *reader,
  struct labcomm2014_error_handler *error,
  struct labcomm2014_memory *memory,
  struct labcomm2014_scheduler *scheduler)
{
  struct decoder *result;

  result = labcomm2014_memory_alloc(memory, 0, sizeof(*result));
  if (result) {
    result->decoder.context = result;
    result->decoder.reader = reader;
    result->decoder.reader->decoder = &result->decoder;
    result->decoder.reader->data = 0;
    result->decoder.reader->data_size = 0;
    result->decoder.reader->count = 0;
    result->decoder.reader->pos = 0;
    result->decoder.reader->error = 0;
    result->decoder.reader_allocated = 0;
    result->decoder.version_ok = 0;
    result->decoder.error = error;
    result->decoder.memory = memory;
    result->decoder.scheduler = scheduler;
    result->decoder.on_error = labcomm20142014_on_error_fprintf;
712
713
714
715
    result->decoder.free = do_free;
    result->decoder.decode_one = do_decode_one;
    result->decoder.ref_register = do_ref_register;
    result->decoder.sample_register = do_register_sample;
716
    result->decoder.ioctl = do_ioctl;
717
718
    result->decoder.index_to_sample_ref = do_index_to_sample_ref;
    result->decoder.ref_get = do_ref_get;
719
720
721
722
723
724
725
726
727
728
    LABCOMM_SIGNATURE_ARRAY_INIT(result->local, struct sample_entry);
    LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local, int);
    LABCOMM_SIGNATURE_ARRAY_INIT(result->local_ref, 
                                 const struct labcomm2014_signature*);
    LABCOMM_SIGNATURE_ARRAY_INIT(result->remote_to_local_ref, int);
  }
  return &(result->decoder);
}


729
const struct labcomm2014_sample_ref *labcomm2014_decoder_get_sample_ref(
Anders Blomdell's avatar
Anders Blomdell committed
730
731
732
  struct labcomm2014_decoder *decoder,
  const struct labcomm2014_signature *signature)
{
733
  return decoder->ref_get(decoder, signature);
Anders Blomdell's avatar
Anders Blomdell committed
734
735
}