/[zanavi_public1]/navit/navit/maptool/osm_protobuf.c
ZANavi

Diff of /navit/navit/maptool/osm_protobuf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 8 Revision 31
1/**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2011 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
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 General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19#include <string.h>
20#include <stdlib.h>
21#include <math.h>
22#include <unistd.h>
23#include <time.h>
24#include <zlib.h>
25#include "maptool.h"
26#include "debug.h"
27#include "linguistics.h"
28#include "file.h"
29#include "generated-code/fileformat.pb-c.h"
30#include "generated-code/osmformat.pb-c.h"
31
32
33static double latlon_scale=10000000.0;
34
35static OSMPBF__BlobHeader *
36read_header(FILE *f)
37{
38 unsigned char *buffer,lenb[4];
39 int len;
40
41 len=sizeof(lenb);
42 if (fread(lenb, 4, 1, f) != 1)
43 return NULL;
44 len=(lenb[0] << 24) | (lenb[1] << 16) | (lenb[2] << 8) | lenb[3];
45 buffer=alloca(len);
46 if (fread(buffer, len, 1, f) != 1)
47 return NULL;
48 return osmpbf__blob_header__unpack(&protobuf_c_system_allocator, len, buffer);
49}
50
51
52static OSMPBF__Blob *
53read_blob(OSMPBF__BlobHeader *header, FILE *f)
54{
55 unsigned char *buffer;
56 int len=header->datasize;
57
58 buffer=alloca(len);
59 if (fread(buffer, len, 1, f) != 1)
60 return NULL;
61 return osmpbf__blob__unpack(&protobuf_c_system_allocator, len, buffer);
62}
63
64static unsigned char *
65uncompress_blob(OSMPBF__Blob *blob)
66{
67 unsigned char *ret=malloc(blob->raw_size);
68 int zerr;
69 z_stream strm;
70
71 if (!ret)
72 return NULL;
73 strm.zalloc = Z_NULL;
74 strm.zfree = Z_NULL;
75 strm.opaque = Z_NULL;
76 strm.avail_in=blob->zlib_data.len;
77 strm.next_in=blob->zlib_data.data;
78 strm.avail_out=blob->raw_size;
79 strm.next_out=ret;
80 zerr = inflateInit(&strm);
81 if (zerr != Z_OK) {
82 free(ret);
83 return NULL;
84 }
85 zerr = inflate(&strm, Z_NO_FLUSH);
86 if (zerr != Z_STREAM_END) {
87 free(ret);
88 return NULL;
89 }
90 inflateEnd(&strm);
91 return ret;
92}
93
94static int
95get_string(char *buffer, int buffer_size, OSMPBF__PrimitiveBlock *primitive_block, int id, int escape)
96{
97 int len=primitive_block->stringtable->s[id].len;
98 char *data=(char *)primitive_block->stringtable->s[id].data;
99 if (primitive_block->stringtable->s[id].len >= buffer_size) {
100 buffer[0]='\0';
101 return 0;
102 }
103 if (escape) {
104 int i;
105 char *p=buffer;
106 for (i = 0 ; i < len ; i++) {
107 switch(data[i]) {
108 case '\t':
109 case '\r':
110 case '\n':
111 case '>':
112 case '<':
113 case '\'':
114 case '"':
115 case '&':
116 sprintf(p,"&#%d;",data[i]);
117 p+=strlen(p);
118 break;
119 default:
120 *p++=data[i];
121 }
122 }
123 *p++='\0';
124 return 1;
125 } else {
126 strncpy(buffer, data, len);
127 buffer[len]='\0';
128 return 1;
129 }
130}
131
132
133static void
134process_osmheader(OSMPBF__Blob *blob, unsigned char *data)
135{
136 OSMPBF__HeaderBlock *header_block;
137 header_block=osmpbf__header_block__unpack(&protobuf_c_system_allocator, blob->raw_size, data);
138 osmpbf__header_block__free_unpacked(header_block, &protobuf_c_system_allocator);
139}
140
141#if 0
142
143static void
144process_user(OSMPBF__PrimitiveBlock *primitive_block, int user_sid, int uid, int swap)
145{
146 char userbuff[1024];
147 get_string(userbuff, sizeof(userbuff), primitive_block, user_sid, 1);
148 if (userbuff[0] && uid != -1) {
149 if (swap)
150 printf(" uid=\"%d\" user=\"%s\"",uid,userbuff);
151 else
152 printf(" user=\"%s\" uid=\"%d\"",userbuff,uid);
153 }
154}
155
156static void
157process_timestamp(long long timestamp)
158{
159 time_t ts;
160 struct tm *tm;
161 char tsbuff[1024];
162 ts=timestamp;
163 tm=gmtime(&ts);
164 strftime(tsbuff, sizeof(tsbuff), "%Y-%m-%dT%H:%M:%SZ", tm);
165 printf(" timestamp=\"%s\"",tsbuff);
166}
167
168#endif
169
170static void
171process_tag(OSMPBF__PrimitiveBlock *primitive_block, int key, int val)
172{
173 char keybuff[1024];
174 char valbuff[1024];
175#if 0
176 get_string(keybuff, sizeof(keybuff), primitive_block, key, 1);
177 get_string(valbuff, sizeof(valbuff), primitive_block, val, 1);
178 printf("\t\t<tag k=\"%s\" v=\"%s\" />\n",keybuff,valbuff);
179#else
180 get_string(keybuff, sizeof(keybuff), primitive_block, key, 0);
181 get_string(valbuff, sizeof(valbuff), primitive_block, val, 0);
182 osm_add_tag(keybuff, valbuff);
183#endif
184}
185
186
187static void
188process_dense(OSMPBF__PrimitiveBlock *primitive_block, OSMPBF__DenseNodes *dense, FILE *out_nodes)
189{
190 int i,j=0,has_tags;
191 long long id=0,lat=0,lon=0,changeset=0,timestamp=0;
192 int version,user_sid=0,uid=0;
193
194 if (!dense)
195 return;
196
197 for (i = 0 ; i < dense->n_id ; i++) {
198 id+=dense->id[i];
199 lat+=dense->lat[i];
200 lon+=dense->lon[i];
201 version=dense->denseinfo->version[i];
202 changeset+=dense->denseinfo->changeset[i];
203 user_sid+=dense->denseinfo->user_sid[i];
204 uid+=dense->denseinfo->uid[i];
205 timestamp+=dense->denseinfo->timestamp[i];
206 has_tags=dense->keys_vals && dense->keys_vals[j];
207 osm_add_node(id, lat/latlon_scale,lon/latlon_scale);
208#if 0
209 printf("\t<node id=\"%Ld\" lat=\"%.7f\" lon=\"%.7f\" version=\"%d\" changeset=\"%Ld\"",id,lat/latlon_scale,lon/latlon_scale,version,changeset);
210 process_user(primitive_block, user_sid, uid, 0);
211 process_timestamp(timestamp);
212#endif
213 if (has_tags) {
214#if 0
215 printf(">\n");
216#endif
217 while (dense->keys_vals[j]) {
218 process_tag(primitive_block, dense->keys_vals[j], dense->keys_vals[j+1]);
219 j+=2;
220 }
221#if 0
222 printf("\t</node>\n");
223 } else
224 printf("/>\n");
225#else
226 }
227#endif
228 osm_end_node(out_nodes);
229 j++;
230 }
231}
232
233#if 0
234static void
235process_info(OSMPBF__PrimitiveBlock *primitive_block, OSMPBF__Info *info)
236{
237 printf(" version=\"%d\" changeset=\"%Ld\"",info->version,info->changeset);
238 process_user(primitive_block, info->user_sid, info->uid, 1);
239 process_timestamp(info->timestamp);
240}
241#endif
242
243static void
244process_way(OSMPBF__PrimitiveBlock *primitive_block, OSMPBF__Way *way, FILE *out_ways)
245{
246 int i;
247 long long ref=0;
248
249 osm_add_way(way->id);
250#if 0
251 printf("\t<way id=\"%Ld\"",way->id);
252 process_info(primitive_block, way->info);
253 printf(">\n");
254#else
255#endif
256 for (i = 0 ; i < way->n_refs ; i++) {
257 ref+=way->refs[i];
258 osm_add_nd(ref);
259#if 0
260 printf("\t\t<nd ref=\"%Ld\"/>\n",ref);
261#else
262#endif
263 }
264 for (i = 0 ; i < way->n_keys ; i++)
265 process_tag(primitive_block, way->keys[i], way->vals[i]);
266#if 0
267 printf("\t</way>\n");
268#endif
269 osm_end_way(out_ways);
270}
271
272static void
273process_relation(OSMPBF__PrimitiveBlock *primitive_block, OSMPBF__Relation *relation, FILE *out_turn_restrictions, FILE *out_boundaries)
274{
275 int i;
276 long long ref=0;
277 char rolebuff[1024];
278
279#if 0
280 printf("\t<relation id=\"%Ld\"",relation->id);
281 process_info(primitive_block, relation->info);
282 printf(">\n");
283#endif
284 osm_add_relation(relation->id);
285 for (i = 0 ; i < relation->n_roles_sid ; i++) {
286#if 0
287 printf("\t\t<member type=\"");
288 switch (relation->types[i]) {
289 case 0:
290 printf("node");
291 break;
292 case 1:
293 printf("way");
294 break;
295 case 2:
296 printf("relation");
297 break;
298 default:
299 printf("unknown");
300 break;
301 }
302#endif
303 ref+=relation->memids[i];
304 get_string(rolebuff, sizeof(rolebuff), primitive_block, relation->roles_sid[i], 1);
305#if 0
306 printf("\" ref=\"%Ld\" role=\"%s\"/>\n",ref,rolebuff);
307#else
308 osm_add_member(relation->types[i]+1,ref,rolebuff);
309#endif
310 }
311 for (i = 0 ; i < relation->n_keys ; i++)
312 process_tag(primitive_block, relation->keys[i], relation->vals[i]);
313#if 0
314 printf("\t</relation>\n");
315#else
316 osm_end_relation(out_turn_restrictions, out_boundaries);
317#endif
318}
319
320static void
321process_osmdata(OSMPBF__Blob *blob, unsigned char *data, FILE *out_nodes, FILE *out_ways, FILE *out_turn_restrictions, FILE *out_boundaries)
322{
323 int i,j;
324 OSMPBF__PrimitiveBlock *primitive_block;
325 primitive_block=osmpbf__primitive_block__unpack(&protobuf_c_system_allocator, blob->raw_size, data);
326 for (i = 0 ; i < primitive_block->n_primitivegroup ; i++) {
327 OSMPBF__PrimitiveGroup *primitive_group=primitive_block->primitivegroup[i];
328 process_dense(primitive_block, primitive_group->dense, out_nodes);
329 for (j = 0 ; j < primitive_group->n_ways ; j++)
330 process_way(primitive_block, primitive_group->ways[j], out_ways);
331 for (j = 0 ; j < primitive_group->n_relations ; j++)
332 process_relation(primitive_block, primitive_group->relations[j], out_turn_restrictions, out_boundaries);
333#if 0
334 printf("Group %p %d %d %d %d\n",primitive_group->dense,primitive_group->n_nodes,primitive_group->n_ways,primitive_group->n_relations,primitive_group->n_changesets);
335#endif
336 }
337 osmpbf__primitive_block__free_unpacked(primitive_block, &protobuf_c_system_allocator);
338}
339
340
341int
342map_collect_data_osm_protobuf(FILE *in, FILE *out_ways, FILE *out_nodes, FILE *out_turn_restrictions, FILE *out_boundaries)
343{
344 OSMPBF__BlobHeader *header;
345 OSMPBF__Blob *blob;
346 unsigned char *data;
347#if 0
348 printf("<?xml version='1.0' encoding='UTF-8'?>\n");
349 printf("<osm version=\"0.6\" generator=\"pbf2osm\">\n");
350#endif
351 while ((header=read_header(in))) {
352 blob=read_blob(header, in);
353 data=uncompress_blob(blob);
354 if (!strcmp(header->type,"OSMHeader")) {
355 process_osmheader(blob, data);
356 } else if (!strcmp(header->type,"OSMData")) {
357 process_osmdata(blob, data, out_nodes, out_ways, out_turn_restrictions, out_boundaries);
358 } else {
359 printf("unknown\n");
360 return 0;
361 }
362 free(data);
363 osmpbf__blob__free_unpacked(blob, &protobuf_c_system_allocator);
364 osmpbf__blob_header__free_unpacked(header, &protobuf_c_system_allocator);
365 }
366#if 0
367 printf("</osm>\n");
368#endif
369 return 1;
370}

Legend:
Removed from v.8  
changed lines
  Added in v.31

   
Visit the ZANavi Wiki