Fix:Core:Better win32 module loading
[navit-package] / navit / maptool / itembin.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include "maptool.h"
4 #include "linguistics.h"
5 #include "file.h"
6 #include "debug.h"
7
8
9
10 struct item_bin *
11 read_item(FILE *in)
12 {
13         struct item_bin *ib=(struct item_bin *) buffer;
14         int r,s;
15         r=fread(ib, sizeof(*ib), 1, in);
16         if (r != 1)
17                 return NULL;
18         bytes_read+=r;
19         dbg_assert((ib->len+1)*4 < sizeof(buffer));
20         s=(ib->len+1)*4-sizeof(*ib);
21         r=fread(ib+1, s, 1, in);
22         if (r != 1)
23                 return NULL;
24         bytes_read+=r;
25         return ib;
26 }
27
28 int
29 item_bin_read(struct item_bin *ib, FILE *in)
30 {
31         if (fread(ib, 4, 1, in) == 0)
32                 return 0;
33         if (!ib->len)
34                 return 1;
35         if (fread((unsigned char *)ib+4, ib->len*4, 1, in))
36                 return 2;
37         return 0;
38 }
39
40 void
41 item_bin_set_type(struct item_bin *ib, enum item_type type)
42 {
43         ib->type=type;
44 }
45
46 void
47 item_bin_init(struct item_bin *ib, enum item_type type)
48 {
49         ib->clen=0;
50         ib->len=2;
51         item_bin_set_type(ib, type);
52 }
53
54
55 void
56 item_bin_add_coord(struct item_bin *ib, struct coord *c, int count)
57 {
58         struct coord *c2=(struct coord *)(ib+1);
59         c2+=ib->clen/2;
60         memcpy(c2, c, count*sizeof(struct coord));
61         ib->clen+=count*2;
62         ib->len+=count*2;
63 }
64
65 void
66 item_bin_bbox(struct item_bin *ib, struct rect *r)
67 {
68         struct coord c;
69         item_bin_add_coord(ib, &r->l, 1);
70         c.x=r->h.x;
71         c.y=r->l.y;
72         item_bin_add_coord(ib, &c, 1);
73         item_bin_add_coord(ib, &r->h, 1);
74         c.x=r->l.x;
75         c.y=r->h.y;
76         item_bin_add_coord(ib, &c, 1);
77         item_bin_add_coord(ib, &r->l, 1);
78 }
79
80 void
81 item_bin_copy_coord(struct item_bin *ib, struct item_bin *from, int dir)
82 {
83         struct coord *c=(struct coord *)(from+1);
84         int i,count=from->clen/2;
85         if (dir >= 0) {
86                 item_bin_add_coord(ib, c, count);
87                 return;
88         }
89         for (i = 1 ; i <= count ; i++) 
90                 item_bin_add_coord(ib, &c[count-i], 1);
91 }
92
93 void
94 item_bin_add_coord_rect(struct item_bin *ib, struct rect *r)
95 {
96         item_bin_add_coord(ib, &r->l, 1);
97         item_bin_add_coord(ib, &r->h, 1);
98 }
99
100 void
101 item_bin_add_attr_data(struct item_bin *ib, enum attr_type type, void *data, int size)
102 {
103         struct attr_bin *ab=(struct attr_bin *)((int *)ib+ib->len+1);
104         int pad=(4-(size%4))%4;
105         ab->type=type;
106         memcpy(ab+1, data, size);
107         memset((unsigned char *)(ab+1)+size, 0, pad);
108         ab->len=(size+pad)/4+1;
109         ib->len+=ab->len+1;
110 }
111
112 void
113 item_bin_add_attr(struct item_bin *ib, struct attr *attr)
114 {
115         item_bin_add_attr_data(ib, attr->type, attr_data_get(attr), attr_data_size(attr));
116 }
117
118 void
119 item_bin_add_attr_int(struct item_bin *ib, enum attr_type type, int val)
120 {
121         struct attr attr;
122         attr.type=type;
123         attr.u.num=val;
124         item_bin_add_attr(ib, &attr);
125 }
126
127 void *
128 item_bin_get_attr(struct item_bin *ib, enum attr_type type, void *last)
129 {
130         unsigned char *s=(unsigned char *)ib;
131         unsigned char *e=s+(ib->len+1)*4;
132         s+=sizeof(struct item_bin)+ib->clen*4;
133         while (s < e) {
134                 struct attr_bin *ab=(struct attr_bin *)s;
135                 s+=(ab->len+1)*4;
136                 if (ab->type == type && (void *)(ab+1) > last) {
137                         return (ab+1);
138                 }
139         }
140         return NULL;
141 }
142
143 struct attr_bin *
144 item_bin_get_attr_bin_last(struct item_bin *ib)
145 {
146         struct attr_bin *ab=NULL;
147         unsigned char *s=(unsigned char *)ib;
148         unsigned char *e=s+(ib->len+1)*4;
149         s+=sizeof(struct item_bin)+ib->clen*4;
150         while (s < e) {
151                 ab=(struct attr_bin *)s;
152                 s+=(ab->len+1)*4;
153         }
154         return ab;
155 }
156
157 void
158 item_bin_add_attr_longlong(struct item_bin *ib, enum attr_type type, long long val)
159 {
160         struct attr attr;
161         attr.type=type;
162         attr.u.num64=&val;
163         item_bin_add_attr(ib, &attr);
164 }
165
166 void
167 item_bin_add_attr_string(struct item_bin *ib, enum attr_type type, char *str)
168 {
169         struct attr attr;
170         if (! str)
171                 return;
172         attr.type=type;
173         attr.u.str=str;
174         item_bin_add_attr(ib, &attr);
175 }
176
177 void
178 item_bin_add_attr_range(struct item_bin *ib, enum attr_type type, short min, short max)
179 {
180         struct attr attr;
181         attr.type=type;
182         attr.u.range.min=min;
183         attr.u.range.max=max;
184         item_bin_add_attr(ib, &attr);
185 }
186
187 void
188 item_bin_write(struct item_bin *ib, FILE *out)
189 {
190         fwrite(ib, (ib->len+1)*4, 1, out);
191 }
192
193 void
194 item_bin_write_clipped(struct item_bin *ib, struct tile_parameter *param, struct item_bin_sink *out)
195 {
196         struct tile_data tile_data;
197         int i;
198         bbox((struct coord *)(ib+1), ib->clen/2, &tile_data.item_bbox);
199         tile_data.buffer[0]='\0';
200         tile_data.tile_depth=tile(&tile_data.item_bbox, NULL, tile_data.buffer, param->max, param->overlap, &tile_data.tile_bbox);
201         if (tile_data.tile_depth == param->max || tile_data.tile_depth >= param->min) {
202                 item_bin_write_to_sink(ib, out, &tile_data);
203                 return;
204         }
205         for (i = 0 ; i < 4 ; i++) {
206                 struct rect clip_rect;
207                 tile_data.buffer[tile_data.tile_depth]='a'+i;
208                 tile_data.buffer[tile_data.tile_depth+1]='\0';
209                 tile_bbox(tile_data.buffer, &clip_rect, param->overlap);
210                 if (ib->type < type_area)
211                         clip_line(ib, &clip_rect, param, out);
212                 else
213                         clip_polygon(ib, &clip_rect, param, out);
214         }
215 }
216
217 static char *
218 coord_to_str(struct coord *c)
219 {
220         int x=c->x;
221         int y=c->y;
222         char *sx="";
223         char *sy="";
224         if (x < 0) {
225                 sx="-";
226                 x=-x;
227         }
228         if (y < 0) {
229                 sy="-";
230                 y=-y;
231         }
232         return g_strdup_printf("%s0x%x %s0x%x",sx,x,sy,y);
233 }
234
235 static void
236 dump_coord(struct coord *c, FILE *out)
237 {
238         char *str=coord_to_str(c);
239         fprintf(out,"%s",str);
240         g_free(str);
241 }
242
243
244 void
245 item_bin_dump(struct item_bin *ib, FILE *out)
246 {
247         struct coord *c;
248         struct attr_bin *a;
249         struct attr attr;
250         int *attr_start;
251         int *attr_end;
252         int i;
253         char *str;
254
255         c=(struct coord *)(ib+1);
256         if (ib->type < type_line) {
257                 dump_coord(c,out);
258                 fprintf(out, " ");
259         }
260         attr_start=(int *)(ib+1)+ib->clen;
261         attr_end=(int *)ib+ib->len+1;
262         fprintf(out,"type=%s", item_to_name(ib->type));
263         while (attr_start < attr_end) {
264                 a=(struct attr_bin *)(attr_start);
265                 attr_start+=a->len+1;
266                 attr.type=a->type;
267                 attr_data_set(&attr, (a+1));
268                 str=attr_to_text(&attr, NULL, 1);
269                 fprintf(out," %s=\"%s\"", attr_to_name(a->type), str);
270                 g_free(str);
271         }
272         fprintf(out," debug=\"length=%d\"", ib->len);
273         fprintf(out,"\n");
274         if (ib->type >= type_line) {
275                 for (i = 0 ; i < ib->clen/2 ; i++) {
276                         dump_coord(c+i,out);
277                         fprintf(out,"\n");
278                 }
279         }
280 }
281
282 void
283 dump_itembin(struct item_bin *ib)
284 {
285         item_bin_dump(ib, stdout);
286 }
287
288 struct population_table {
289         enum item_type type;
290         int population;
291 };
292
293 static struct population_table town_population[] = {
294         {type_town_label_0e0,0},
295         {type_town_label_1e0,1},
296         {type_town_label_2e0,2},
297         {type_town_label_5e0,5},
298         {type_town_label_1e1,10},
299         {type_town_label_2e1,20},
300         {type_town_label_5e1,50},
301         {type_town_label_1e2,100},
302         {type_town_label_2e2,200},
303         {type_town_label_5e2,500},
304         {type_town_label_1e3,1000},
305         {type_town_label_2e3,2000},
306         {type_town_label_5e3,5000},
307         {type_town_label_1e4,10000},
308         {type_town_label_2e4,20000},
309         {type_town_label_5e4,50000},
310         {type_town_label_1e5,100000},
311         {type_town_label_2e5,200000},
312         {type_town_label_5e5,500000},
313         {type_town_label_1e6,1000000},
314         {type_town_label_2e6,2000000},
315         {type_town_label_5e6,5000000},
316         {type_town_label_1e7,10000000},
317 };
318
319 static struct population_table district_population[] = {
320         {type_district_label_0e0,0},
321         {type_district_label_1e0,1},
322         {type_district_label_2e0,2},
323         {type_district_label_5e0,5},
324         {type_district_label_1e1,10},
325         {type_district_label_2e1,20},
326         {type_district_label_5e1,50},
327         {type_district_label_1e2,100},
328         {type_district_label_2e2,200},
329         {type_district_label_5e2,500},
330         {type_district_label_1e3,1000},
331         {type_district_label_2e3,2000},
332         {type_district_label_5e3,5000},
333         {type_district_label_1e4,10000},
334         {type_district_label_2e4,20000},
335         {type_district_label_5e4,50000},
336         {type_district_label_1e5,100000},
337         {type_district_label_2e5,200000},
338         {type_district_label_5e5,500000},
339         {type_district_label_1e6,1000000},
340         {type_district_label_2e6,2000000},
341         {type_district_label_5e6,5000000},
342         {type_district_label_1e7,10000000},
343 };
344
345 void
346 item_bin_set_type_by_population(struct item_bin *ib, int population)
347 {
348         struct population_table *table;
349         int i,count;
350
351         if (population < 0)
352                 population=0;
353         if (item_is_district(*item_bin)) {
354                 table=district_population;
355                 count=sizeof(district_population)/sizeof(district_population[0]);
356         } else {
357                 table=town_population;
358                 count=sizeof(town_population)/sizeof(town_population[0]);
359         }
360         for (i = 0 ; i < count ; i++) {
361                 if (population < table[i].population)
362                         break;
363         }
364         item_bin_set_type(ib, table[i-1].type);
365 }
366
367
368 void
369 item_bin_write_match(struct item_bin *ib, enum attr_type type, enum attr_type match, FILE *out)
370 {
371         char *word=item_bin_get_attr(ib, type, NULL);
372         int i,words=0,len=ib->len;
373         if (!word)
374                 return;
375         do  {
376                 for (i = 0 ; i < 3 ; i++) {
377                                 char *str=linguistics_expand_special(word, i);
378                                 if (str) {
379                                         ib->len=len;
380                                         if (i || words)
381                                                 item_bin_add_attr_string(ib, match, str);
382                                         item_bin_write(ib, out);
383                                         g_free(str);
384                                 }
385                         }
386                         word=linguistics_next_word(word);
387                         words++;
388         } while (word);
389 }
390
391 static int
392 item_bin_sort_compare(const void *p1, const void *p2)
393 {
394         struct item_bin *ib1=*((struct item_bin **)p1),*ib2=*((struct item_bin **)p2);
395         struct attr_bin *attr1,*attr2;
396         char *s1,*s2;
397         int ret;
398 #if 0
399         dbg_assert(ib1->clen==2);
400         dbg_assert(ib2->clen==2);
401         attr1=(struct attr_bin *)((int *)(ib1+1)+ib1->clen);
402         attr2=(struct attr_bin *)((int *)(ib2+1)+ib1->clen);
403 #else
404         attr1=item_bin_get_attr_bin_last(ib1);
405         attr2=item_bin_get_attr_bin_last(ib2);
406 #endif
407 #if 0
408         dbg_assert(attr1->type == attr_town_name || attr1->type == attr_town_name_match);
409         dbg_assert(attr2->type == attr_town_name || attr2->type == attr_town_name_match);
410 #endif
411         s1=(char *)(attr1+1);
412         s2=(char *)(attr2+1);
413         if (attr1->type == attr_house_number && attr2->type == attr_house_number) {
414                 ret=atoi(s1)-atoi(s2);
415                 if (ret)
416                         return ret;
417         }
418         ret=strcmp(s1, s2);
419         if (!ret) {
420                 int match1=0,match2=0;
421                 match1=(attr1->type == attr_town_name_match || attr1->type == attr_district_name_match);
422                 match2=(attr2->type == attr_town_name_match || attr2->type == attr_district_name_match);
423                 ret=match1-match2;
424         }
425 #if 0
426         fprintf(stderr,"sort_countries_compare p1=%p p2=%p %s %s\n",p1,p2,s1,s2);
427 #endif
428         return ret;
429 }
430
431 int
432 item_bin_sort_file(char *in_file, char *out_file, struct rect *r, int *size)
433 {
434         int j,count;
435         struct coord *c;
436         struct item_bin *ib;
437         FILE *f;
438         unsigned char *p,**idx,*buffer;
439         if (file_get_contents(in_file, &buffer, size)) {
440                 ib=(struct item_bin *)buffer;
441                 p=buffer;
442                 count=0;
443                 while (p < buffer+*size) {
444                         count++;
445                         p+=(*((int *)p)+1)*4;
446                 }
447                 idx=malloc(count*sizeof(void *));
448                 dbg_assert(idx != NULL);
449                 p=buffer;
450                 for (j = 0 ; j < count ; j++) {
451                         idx[j]=p;
452                         p+=(*((int *)p)+1)*4;
453                 }
454                 qsort(idx, count, sizeof(void *), item_bin_sort_compare);
455                 f=fopen(out_file,"wb");
456                 for (j = 0 ; j < count ; j++) {
457                         ib=(struct item_bin *)(idx[j]);
458                         c=(struct coord *)(ib+1);
459                         fwrite(ib, (ib->len+1)*4, 1, f);
460                         if (r) {
461                                 if (j) 
462                                         bbox_extend(c, r);
463                                 else {
464                                         r->l=*c;
465                                         r->h=*c;
466                                 }
467                         }
468                 }
469                 fclose(f);
470                 return 1;
471         }
472         return 0;
473 }