Subversion Repositories public

Rev

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