/liblo-0.26/src/bundle.c
C | 181 lines | 129 code | 35 blank | 17 comment | 24 complexity | 30b8ee11d27abf175cce0bb90acf42bf MD5 | raw file
Possible License(s): LGPL-2.1
1/*
2 * Copyright (C) 2004 Steve Harris
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * $Id$
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21#include "lo_types_internal.h"
22#include "lo/lo.h"
23
24lo_bundle lo_bundle_new(lo_timetag tt)
25{
26 lo_bundle b = calloc(1, sizeof(struct _lo_bundle));
27
28 b->size = 4;
29 b->len = 0;
30 b->ts = tt;
31 b->msgs = calloc(b->size, sizeof(lo_message));
32 b->paths = calloc(b->size, sizeof(char *));
33
34 return b;
35}
36
37int lo_bundle_add_message(lo_bundle b, const char *path, lo_message m)
38{
39 if (!m)
40 return 0;
41
42 if (b->len >= b->size) {
43 b->size *= 2;
44 b->msgs = realloc(b->msgs, b->size * sizeof(lo_message));
45 b->paths = realloc(b->paths, b->size * sizeof(char *));
46 if (!b->msgs || !b->paths)
47 return -1;
48 }
49
50 b->msgs[b->len] = m;
51 b->paths[b->len] = (char *)path;
52
53 (b->len)++;
54 return 0;
55}
56
57size_t lo_bundle_length(lo_bundle b)
58{
59 size_t size = 16; /* "#bundle" and the timetag */
60 int i;
61
62 if (!b) {
63 return 0;
64 }
65
66 size += b->len * 4; /* sizes */
67 for (i = 0; i < b->len; i++) {
68 size += lo_message_length(b->msgs[i], b->paths[i]);
69 }
70
71 return size;
72}
73
74void *lo_bundle_serialise(lo_bundle b, void *to, size_t *size)
75{
76 size_t s, skip;
77 int32_t *bes;
78 int i;
79 char *pos;
80 lo_pcast32 be;
81
82 if (!b) {
83 return NULL;
84 }
85
86 s = lo_bundle_length(b);
87 if (size) {
88 *size = s;
89 }
90
91 if (!to) {
92 to = calloc(1, s);
93 }
94
95 pos = to;
96 strcpy(pos, "#bundle");
97 pos += 8;
98
99 be.nl = lo_htoo32(b->ts.sec);
100 memcpy(pos, &be, 4);
101 pos += 4;
102 be.nl = lo_htoo32(b->ts.frac);
103 memcpy(pos, &be, 4);
104 pos += 4;
105
106 for (i = 0; i < b->len; i++) {
107 lo_message_serialise(b->msgs[i], b->paths[i], pos + 4, &skip);
108 bes = (int32_t *)pos;
109 *bes = lo_htoo32(skip);
110 pos += skip + 4;
111
112 if (pos > (char *)to + s) {
113 fprintf(stderr, "liblo: data integrity error at message %d\n", i);
114
115 return NULL;
116 }
117 }
118 if (pos != (char*)to + s) {
119 fprintf(stderr, "liblo: data integrity error\n");
120
121 return NULL;
122 }
123
124 return to;
125}
126
127void lo_bundle_free(lo_bundle b)
128{
129 if (!b) {
130 return;
131 }
132
133 free(b->msgs);
134 free(b->paths);
135 free(b);
136}
137
138static int _lo_internal_compare_ptrs( const void* a, const void* b )
139{
140 if (*(void**)a < *(void**)b) return -1;
141 if (*(void**)a == *(void**)b) return 0;
142 return 1;
143}
144
145void lo_bundle_free_messages(lo_bundle b)
146{
147 int i;
148 lo_message tmp = 0;
149
150 if (!b)
151 return;
152
153 /* avoid freeing the same message twice */
154 if (b->len > 2)
155 qsort(b->msgs, b->len, sizeof(lo_message*), _lo_internal_compare_ptrs);
156
157 for(i = 0; i < b->len; i++) {
158 if (b->msgs[i] != tmp) {
159 tmp = b->msgs[i];
160 lo_message_free(b->msgs[i]);
161 }
162 }
163 free(b->msgs);
164 free(b->paths);
165 free(b);
166}
167
168void lo_bundle_pp(lo_bundle b)
169{
170 int i;
171
172 if (!b) return;
173
174 printf("bundle(%f):\n", (double)b->ts.sec + b->ts.frac / 4294967296.0);
175 for (i = 0; i < b->len; i++) {
176 lo_message_pp(b->msgs[i]);
177 }
178 printf("\n");
179}
180
181/* vi:set ts=8 sts=4 sw=4: */