Subversion Repositories public

Rev

Rev 93 | Rev 246 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
93 andreas 1
#include "config.h"
2
#include <string.h>
3
#include <stdlib.h>
4
#include "garmin.h"
5
 
6
 
7
static uint32 gListId = 0;
8
 
9
 
10
garmin_data *
11
garmin_alloc_data ( garmin_datatype type )
12
{
13
  garmin_data * d = malloc(sizeof(garmin_data));
14
 
15
  d->type = type;
16
 
17
#define CASE_DATA(x) \
18
  case data_D##x: d->data = calloc(1,sizeof(D##x)); break
19
 
20
  switch ( type ) {
21
  case data_Dlist: d->data = garmin_alloc_list(); break;
22
  CASE_DATA(100);
23
  CASE_DATA(101);
24
  CASE_DATA(102);
25
  CASE_DATA(103);
26
  CASE_DATA(104);
27
  CASE_DATA(105);
28
  CASE_DATA(106);
29
  CASE_DATA(107);
30
  CASE_DATA(108);
31
  CASE_DATA(109);
32
  CASE_DATA(110);
33
  CASE_DATA(120);
34
  CASE_DATA(150);
35
  CASE_DATA(151);
36
  CASE_DATA(152);
37
  CASE_DATA(154);
38
  CASE_DATA(155);
39
  CASE_DATA(200);
40
  CASE_DATA(201);
41
  CASE_DATA(202);
42
  CASE_DATA(210);
43
  CASE_DATA(300);
44
  CASE_DATA(301);
45
  CASE_DATA(302);
46
  CASE_DATA(303);
47
  CASE_DATA(304);
48
  CASE_DATA(310);
49
  CASE_DATA(311);
50
  CASE_DATA(312);
51
  CASE_DATA(400);
52
  CASE_DATA(403);
53
  CASE_DATA(450);
54
  CASE_DATA(500);
55
  CASE_DATA(501);
56
  CASE_DATA(550);
57
  CASE_DATA(551);
58
  CASE_DATA(600);
59
  CASE_DATA(650);
60
  CASE_DATA(700);
61
  CASE_DATA(800);
62
  CASE_DATA(906);
63
  CASE_DATA(1000);
64
  CASE_DATA(1001);
65
  CASE_DATA(1002);
66
  CASE_DATA(1003);
67
  CASE_DATA(1004);
68
  CASE_DATA(1005);
69
  CASE_DATA(1006);
70
  CASE_DATA(1007);
71
  CASE_DATA(1008);
72
  CASE_DATA(1009);
73
  CASE_DATA(1010);
74
  CASE_DATA(1011);
75
  CASE_DATA(1012);
76
  CASE_DATA(1013);
77
  CASE_DATA(1015);
78
  default: d->data = NULL; break;
79
  }
80
 
81
  return d;
82
}
83
 
84
 
85
garmin_list *
86
garmin_alloc_list ( void )
87
{
88
  garmin_list * l;
89
 
90
  l = calloc(1,sizeof(garmin_list));
91
  l->id = ++gListId;
92
 
93
  return l;
94
}
95
 
96
 
97
garmin_list *
98
garmin_list_append ( garmin_list * list, garmin_data * data )
99
{
100
  garmin_list *      l = list;
101
  garmin_list_node * n;
102
 
103
  if ( data != NULL ) {
104
    if ( l == NULL ) l = garmin_alloc_list();
105
    n = malloc(sizeof(garmin_list_node));
106
 
107
    n->data = data;
108
    n->next = NULL;
136 andreas 109
 
93 andreas 110
    if ( l->head == NULL ) l->head = n;
111
    if ( l->tail != NULL ) l->tail->next = n;
112
    l->tail = n;
136 andreas 113
 
93 andreas 114
    l->elements++;
115
  }
116
 
117
  return l;
118
}
119
 
120
 
121
garmin_data *
122
garmin_list_data ( garmin_data * data, uint32 which )
123
{
124
  garmin_data *       ret = NULL;
125
  garmin_list *       list;
126
  garmin_list_node *  n;
127
  unsigned int        i;
128
 
129
  if ( data                 != NULL       && 
130
       data->type           == data_Dlist && 
131
       (list = data->data)  != NULL ) {
132
    for ( i = 0, n = list->head; i < which && n != NULL; i++, n = n->next );
133
    if ( n != NULL ) ret = n->data;
134
  }
135
 
136
  return ret;
137
}
138
 
139
 
140
void
141
garmin_free_list ( garmin_list * l )
142
{
143
  garmin_list_node * n;
144
  garmin_list_node * x;
145
 
146
  if ( l != NULL ) {
147
    for ( n = l->head; n != NULL; n = x ) {
148
      x = n->next;
149
      garmin_free_data(n->data);
150
      free(n);
151
    }
152
    free(l);
153
  }
154
}
155
 
156
 
157
void
158
garmin_free_list_only ( garmin_list * l )
159
{
160
  garmin_list_node * n;
161
  garmin_list_node * x;
162
 
163
  if ( l != NULL ) {
164
    for ( n = l->head; n != NULL; n = x ) {
165
      x = n->next;
166
      free(n);
167
    }
168
    free(l);
169
  }
170
}
171
 
172
 
173
#define TRYFREE(x) if ( x != NULL ) free(x)
174
 
175
 
176
void
177
garmin_free_data ( garmin_data * d )
178
{
179
  D105 *   d105;
180
  D106 *   d106;
181
  D108 *   d108;
182
  D109 *   d109;
183
  D110 *   d110;
184
  D202 *   d202;
185
  D210 *   d210;
186
  D310 *   d310;
187
  D312 *   d312;
188
  D650 *   d650;
189
 
190
  if ( d != NULL ) {
191
    if ( d->data != NULL ) {
192
      if ( d->type == data_Dlist ) {
193
	garmin_free_list((garmin_list *)d->data);
194
      } else {
195
	switch ( d->type ) {
196
	case data_D105:
197
	  d105 = d->data;
198
	  TRYFREE(d105->wpt_ident);
199
	  break;
200
	case data_D106:
201
	  d106 = d->data;
202
	  TRYFREE(d106->wpt_ident);
203
	  TRYFREE(d106->lnk_ident);
204
	  break;
205
	case data_D108:
206
	  d108 = d->data;
207
	  TRYFREE(d108->ident);
208
	  TRYFREE(d108->comment);
209
	  TRYFREE(d108->facility);
210
	  TRYFREE(d108->city);
211
	  TRYFREE(d108->addr);
212
	  TRYFREE(d108->cross_road);
213
	  break;
214
	case data_D109:
215
	  d109 = d->data;
216
	  TRYFREE(d109->ident);
217
	  TRYFREE(d109->comment);
218
	  TRYFREE(d109->facility);
219
	  TRYFREE(d109->city);
220
	  TRYFREE(d109->addr);
221
	  TRYFREE(d109->cross_road);
222
	  break;
223
	case data_D110:
224
	  d110 = d->data;
225
	  TRYFREE(d110->ident);
226
	  TRYFREE(d110->comment);
227
	  TRYFREE(d110->facility);
228
	  TRYFREE(d110->city);
229
	  TRYFREE(d110->addr);
230
	  TRYFREE(d110->cross_road);
231
	  break;
232
	case data_D202:
233
	  d202 = d->data;
234
	  TRYFREE(d202->rte_ident);
235
	  break;
236
	case data_D210:
237
	  d210 = d->data;
238
	  TRYFREE(d210->ident);
239
	  break;
240
	case data_D310:
241
	  d310 = d->data;
242
	  TRYFREE(d310->trk_ident);
243
	  break;
244
	case data_D312:
245
	  d312 = d->data;
246
	  TRYFREE(d312->trk_ident);
247
	  break;
248
	case data_D650:
249
	  d650 = d->data;
250
	  TRYFREE(d650->departure_name);
251
	  TRYFREE(d650->departure_ident);
252
	  TRYFREE(d650->arrival_name);
253
	  TRYFREE(d650->arrival_ident);
254
	  TRYFREE(d650->ac_id);
255
	  break;
256
	default:
257
	  break;
258
	}
259
	free(d->data);
260
      }
261
    }
262
    free(d);
263
  }
264
}
265
 
266
 
267
/* 
268
   Returns the number of bytes needed in order to serialize the data.  Note
269
   that this is an upper bound!  Some of the Garmin data structures do not
270
   align to word boundaries.  Their memory representation will take up more
271
   bytes than the serialized representation will.
272
*/
273
 
274
uint32
275
garmin_data_size ( garmin_data * d )
276
{
277
  garmin_list *       list;
278
  garmin_list_node *  node;
279
  uint32              bytes = 0;
136 andreas 280
  char                hv0[256];
93 andreas 281
 
282
  /* 
283
     The number of bytes needed in order to serialize a Garmin data structure
284
     is almost equal to the size of its data structure - but not quite.  If
285
     we have variable length strings, we need to add their string lengths
286
     (including space for the terminating '\0') and subtract the size of the 
287
     char * placeholders.  We also need 4 bytes for the data type, and 4
288
     additional bytes in which we store the number of bytes that we should
289
     seek forward in order to skip this record.  This allows us to handle
290
     files that include new, unrecognized data types but still conform to
291
     the file format rules (i.e. we can skip data records that we don't
292
     yet know about).
293
  */
294
 
295
#define ADDBYTES(x,y) \
296
  bytes = sizeof(D##x) + 8 - 3 * y
297
 
298
#define ADDSTRING(x,y) \
299
  if (d##x->y != NULL) bytes += strlen(d##x->y)
300
 
301
#define ADDBYTES1(x,a) \
302
  ADDBYTES(x,1);  \
303
  ADDSTRING(x,a)
304
 
305
#define ADDBYTES2(x,a,b) \
306
  ADDBYTES(x,2);  \
307
  ADDSTRING(x,a); \
308
  ADDSTRING(x,b)
309
 
310
#define ADDBYTES5(x,a,b,c,d,e) \
311
  ADDBYTES(x,5);  \
312
  ADDSTRING(x,a); \
313
  ADDSTRING(x,b); \
314
  ADDSTRING(x,c); \
315
  ADDSTRING(x,d); \
316
  ADDSTRING(x,e)
317
 
318
#define ADDBYTES6(x,a,b,c,d,e,f) \
319
  ADDBYTES(x,6);  \
320
  ADDSTRING(x,a); \
321
  ADDSTRING(x,b); \
322
  ADDSTRING(x,c); \
323
  ADDSTRING(x,d); \
324
  ADDSTRING(x,e); \
325
  ADDSTRING(x,f)
326
 
327
#define DATASIZE0(x)              \
328
  case data_D##x:                 \
329
    {                             \
330
      ADDBYTES(x,0);              \
331
    }                             \
332
    break
333
 
334
#define DATASIZE(x,y)             \
335
  case data_D##x:                 \
336
    {                             \
337
      D##x * d##x = d->data;      \
338
                                  \
339
      y;                          \
340
    }                             \
341
    break
342
 
343
#define DATASIZE1(x,a)             DATASIZE(x,ADDBYTES1(x,a))
344
#define DATASIZE2(x,a,b)           DATASIZE(x,ADDBYTES2(x,a,b))
345
#define DATASIZE5(x,a,b,c,d,e)     DATASIZE(x,ADDBYTES5(x,a,b,c,d,e))
346
#define DATASIZE6(x,a,b,c,d,e,f)   DATASIZE(x,ADDBYTES6(x,a,b,c,d,e,f))
347
 
348
 
349
  if ( d != NULL ) {
350
    if ( d->data != NULL ) {
351
      if ( d->type == data_Dlist ) {
352
	list = d->data;
353
	bytes += 16;  /* { datatype, bytes, list ID, element count } */
354
	for ( node = list->head; node != NULL; node = node->next ) {
355
	  bytes += 4; /* list ID */
356
	  bytes += garmin_data_size(node->data);
357
	}
358
      } else {
359
	switch ( d->type ) {
360
        DATASIZE0(100);
361
        DATASIZE0(101);
362
        DATASIZE0(102);
363
        DATASIZE0(103);
364
        DATASIZE0(104);
365
	DATASIZE1(105,wpt_ident);
366
	DATASIZE2(106,wpt_ident,lnk_ident);
367
	DATASIZE0(107);
368
	DATASIZE6(108,ident,comment,facility,city,addr,cross_road);
369
	DATASIZE6(109,ident,comment,facility,city,addr,cross_road);
370
	DATASIZE6(110,ident,comment,facility,city,addr,cross_road);
371
	DATASIZE0(120);
372
	DATASIZE0(150);
373
	DATASIZE0(151);
374
	DATASIZE0(152);
375
	DATASIZE0(154);
376
	DATASIZE0(155);
377
	DATASIZE0(200);
378
	DATASIZE0(201);
379
	DATASIZE1(202,rte_ident);
380
	DATASIZE1(210,ident);
381
	DATASIZE0(300);
382
	DATASIZE0(301);
383
	DATASIZE0(302);
384
	DATASIZE0(303);
385
	DATASIZE0(304);
386
	DATASIZE1(310,trk_ident);
387
	DATASIZE0(311);
388
	DATASIZE1(312,trk_ident);
389
	DATASIZE0(400);
390
	DATASIZE0(403);
391
	DATASIZE0(450);
392
	DATASIZE0(500);
393
	DATASIZE0(501);
394
	DATASIZE0(550);
395
	DATASIZE0(551);
396
	DATASIZE0(600);
397
	DATASIZE5(650,departure_name,departure_ident,
398
		  arrival_name,arrival_ident,ac_id);
399
	DATASIZE0(700);
400
	DATASIZE0(800);
401
	DATASIZE0(906);
402
	DATASIZE0(1000);
403
	DATASIZE0(1001);
404
	DATASIZE0(1002);
405
	DATASIZE0(1003);
406
	DATASIZE0(1004);
407
	DATASIZE0(1005);
408
	DATASIZE0(1006);
409
	DATASIZE0(1007);
410
	DATASIZE0(1008);
411
	DATASIZE0(1009);
412
	DATASIZE0(1010);
413
	DATASIZE0(1011);
414
	DATASIZE0(1012);
415
	DATASIZE0(1013);
416
	DATASIZE0(1015);
417
	default:
136 andreas 418
	  sprintf(hv0, "garmin_data_size: data type %d not supported!",d->type);
419
	  garmin_queue_error(hv0, err_warning);
93 andreas 420
	  break;
421
	}
422
      }
423
    }
424
  }
425
 
426
  return bytes;
427
}