15 * <tag k=".." v=".." />
27 #define file_nodes "nodes.csv"
28 #define file_nodes_uint "nodes_uint.csv"
29 #define file_nodes_gis "nodes_gis.csv"
30 #define file_node_tags "node_tags.csv"
31 #define file_ways "ways.csv"
32 #define file_way_tags "way_tags.csv"
33 #define file_way_nds "way_nds.csv"
34 #define file_relations "relations.csv"
35 #define file_relation_tags "relation_tags.csv"
36 #define file_relation_member_node "relation_member_node.csv"
37 #define file_relation_member_relation "relation_member_relation.csv"
38 #define file_relation_member_way "relation_member_way.csv"
40 unsigned int coordtouint(char *input
) {
41 double maxbit
= (double) 4294967296.0 / (double) 360.0;
42 double proper
= strtod(input
, NULL
) * maxbit
;
43 return (unsigned int) proper
;
46 char * escape_string(char *instr
)
48 unsigned int i
, j
=0, need
= 0;
49 unsigned int len
= strlen(instr
);
53 if (instr
[i
]=='\\' || instr
[i
]=='\'') need
++;
56 outstr
= malloc(len
+ 1);
58 for (i
=0;i
<=strlen(instr
);i
++) {
59 if (instr
[i
]=='\\' || instr
[i
]=='\'')
67 static void parser(char *range
, unsigned long int max
) {
68 typedef enum { OSM
= 0, NODE
= 1, WAY
= 2, RELATION
= 3, TAG
= 4, ND
= 5, MEMBER
= 6 } osm_state_t
;
69 typedef enum { UNKNOWN
= 0, ID
, LAT
, LON
, USER
, TIMESTAMP
, KEY
, VALUE
, TYPE
, REF
, ROLE
} key_state_t
;
70 char *attr_id
= NULL
, *attr_lat
= NULL
, *attr_lon
= NULL
, *attr_user
= NULL
, *attr_timestamp
= NULL
, *attr_key
= NULL
, *attr_value
= NULL
,
71 *attr_type
= NULL
, *attr_ref
= NULL
, *attr_role
= NULL
;
73 unsigned int attr_lat_uint
= 0;
74 unsigned int attr_lon_uint
= 0;
76 FILE *fd_nodes
= fopen(file_nodes
, "w");
77 if (fd_nodes
== NULL
) { perror("Open:"); exit(-1); }
78 FILE *fd_nodes_uint
= fopen(file_nodes_uint
, "w");
79 if (fd_nodes_uint
== NULL
) { perror("Open:"); exit(-1); }
80 FILE *fd_nodes_gis
= fopen(file_nodes_gis
, "w");
81 if (fd_nodes_gis
== NULL
) { perror("Open:"); exit(-1); }
82 FILE *fd_node_tags
= fopen(file_node_tags
, "w");
83 if (fd_node_tags
== NULL
) { perror("Open:"); exit(-1); }
84 FILE *fd_ways
= fopen(file_ways
, "w");
85 if (fd_ways
== NULL
) { perror("Open:"); exit(-1); }
86 FILE *fd_way_tags
= fopen(file_way_tags
, "w");
87 if (fd_way_tags
== NULL
) { perror("Open:"); exit(-1); }
88 FILE *fd_way_nds
= fopen(file_way_nds
, "w");
89 if (fd_way_nds
== NULL
) { perror("Open:"); exit(-1); }
90 FILE *fd_relations
= fopen(file_relations
, "w");
91 if (fd_relations
== NULL
) { perror("Open:"); exit(-1); }
92 FILE *fd_relation_tags
= fopen(file_relation_tags
, "w");
93 if (fd_relation_tags
== NULL
) { perror("Open:"); exit(-1); }
94 FILE *fd_members_node
= fopen(file_relation_member_node
, "w");
95 if (fd_members_node
== NULL
) { perror("Open:"); exit(-1); }
96 FILE *fd_members_relation
= fopen(file_relation_member_relation
, "w");
97 if (fd_members_relation
== NULL
) { perror("Open:"); exit(-1); }
98 FILE *fd_members_way
= fopen(file_relation_member_way
, "w");
99 if (fd_members_way
== NULL
) { perror("Open:"); exit(-1); }
101 unsigned long int count_nodes
= 0, count_node_tags
= 0,
102 count_ways
= 0, count_way_tags
= 0, count_way_nds
= 0,
103 count_relations
= 0, count_relation_tags
= 0, count_members_node
= 0, count_members_relation
= 0, count_members_way
= 0;
105 unsigned long int sequence
= 0;
108 osm_state_t current_tag
= OSM
;
109 osm_state_t parent_tag
= OSM
;
111 char *start
, *end
, *nodename
, *nodename_end
;
114 end
= strchrnul((const char*) start
, '\n');
116 if (strncmp(start
, "<?xml", 5) != 0)
120 end
= strchrnul((const char*) start
, '\n');
122 if (strncmp(start
, "<osm", 4) != 0)
128 end
= strchrnul((const char*) start
, '\n');
130 nodename
= strchrnul(start
, '<') + 1;
131 nodename_end
= strchrnul(nodename
, ' ');
133 if (nodename
[0] == '/') {
137 free(attr_timestamp
);
144 attr_timestamp
= NULL
;
152 switch (nodename_end
- nodename
) {
157 switch (nodename
[0]) {
168 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
176 current_tag
= MEMBER
;
179 current_tag
= RELATION
;
182 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
186 char *key
, *key_end
, *value_end
;
187 key
= nodename_end
+ 1;
191 key_state_t current_key
= UNKNOWN
;
192 key_end
= strchrnul(key
, '=');
194 if (key_end
== NULL
|| key_end
>= end
)
197 switch (key_end
- key
) {
207 current_key
= UNKNOWN
;
226 current_key
= UNKNOWN
;
227 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
243 current_key
= UNKNOWN
;
244 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
249 current_key
= TIMESTAMP
;
252 char *thingie
= strndup(key
, (key_end
- key
));
253 current_key
= UNKNOWN
;
255 fprintf(stderr
, "UNKNOWN ATTR %s-> %c%c\n", thingie
, key
[0], key
[1]);
262 value_end
= strchr(value_end
, '"');
267 switch (current_key
) {
269 if (attr_id
) free(attr_id
);
270 attr_id
= strndup(value
, (value_end
- value
));
274 if (attr_lat
) free(attr_lat
);
275 attr_lat
= strndup(value
, (value_end
- value
));
276 attr_lat_uint
= coordtouint(attr_lat
);
280 if (attr_lon
) free(attr_lon
);
281 attr_lon
= strndup(value
, (value_end
- value
));
282 attr_lon_uint
= coordtouint(attr_lon
);
286 if (attr_timestamp
) free(attr_timestamp
);
287 attr_timestamp
= strndup(value
, (value_end
- value
));
288 // attr_timestamp[10] = ' '; /* Stupid timestamp fix */
293 if (attr_user
) free(attr_user
);
294 attr_user
= strndup(value
, (value_end
- value
));
295 tmp
= escape_string(attr_user
);
303 if (attr_key
) free(attr_key
);
304 attr_key
= strndup(value
, (value_end
- value
));
305 tmp
= escape_string(attr_key
);
313 if (attr_value
) free(attr_value
);
314 attr_value
= strndup(value
, (value_end
- value
));
315 tmp
= escape_string(attr_value
);
322 if (attr_type
) free(attr_type
);
323 attr_type
= strndup(value
, (value_end
- value
));
327 if (attr_ref
) free(attr_ref
);
328 attr_ref
= strndup(value
, (value_end
- value
));
333 if (attr_role
) free(attr_role
);
334 attr_role
= strndup(value
, (value_end
- value
));
335 tmp
= escape_string(attr_role
);
342 fprintf(stderr
, "--> %c%c\n", value
[0], value
[1]);
348 switch (current_tag
) {
350 fprintf(fd_nodes
, "%s, %s, %s, '%s', %s\n", attr_id
, attr_lat
, attr_lon
, attr_user
, attr_timestamp
);
351 fprintf(fd_nodes_uint
, "%s, %d, %d, '%s', %s\n", attr_id
, attr_lat_uint
, attr_lon_uint
, attr_user
, attr_timestamp
);
352 fprintf(fd_nodes_gis
, "%s, 'POINT( %s %s )', '%s', %s\n", attr_id
, attr_lon
, attr_lat
, attr_user
, attr_timestamp
);
356 switch (parent_tag
) {
358 fprintf(fd_node_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
362 fprintf(fd_way_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
366 fprintf(fd_relation_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
367 count_relation_tags
++;
375 fprintf(fd_ways
, "%s, '%s', '%s'\n", attr_id
, attr_user
, attr_timestamp
);
377 // fprintf(fd_way_tags, "%s, '%s', '%s'\n", attr_id, "type", "way");
381 fprintf(fd_relations
, "%s, '%s', '%s'\n", attr_id
, attr_user
, attr_timestamp
);
385 if (strcmp(attr_type
, "node") == 0) {
386 fprintf(fd_members_node
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
387 count_members_node
++;
388 } else if (strcmp(attr_type
, "way") == 0) {
389 fprintf(fd_members_way
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
391 } else if (strcmp(attr_type
, "relation") == 0) {
392 fprintf(fd_members_relation
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
393 count_members_relation
++;
398 fprintf(fd_way_nds
, "%s, %lu, %s\n", attr_id
, sequence
, attr_ref
);
406 if (end
[-2] == '/') {
407 switch (current_tag
) {
420 free(attr_timestamp
);
425 attr_timestamp
= NULL
;
450 } else if (current_tag
== NODE
|| current_tag
== WAY
|| current_tag
== RELATION
) {
451 parent_tag
= current_tag
;
454 } while ((start
= ++end
) < (range
+ max
));
459 free(attr_timestamp
);
466 fclose(fd_nodes_uint
);
467 fclose(fd_nodes_gis
);
468 fclose(fd_node_tags
);
472 fclose(fd_relations
);
473 fclose(fd_relation_tags
);
474 fclose(fd_members_node
);
475 fclose(fd_members_relation
);
477 char *current
= get_current_dir_name();
479 printf("START TRANSACTION;\n");
481 printf("CREATE TABLE nodes_legacy (id serial, long double, lat double, username varchar(255), timestamp timestamptz);\n");
482 printf("CREATE TABLE nodes_legacy_uint (id serial, long integer, lat integer, username varchar(255), timestamp timestamptz);\n");
483 printf("CREATE TABLE nodes_legacy_gis (id serial, poi point, username varchar(255), timestamp timestamptz);\n");
484 printf("CREATE TABLE node_tags (node integer, k varchar(255), v varchar(1024), primary key (node, k), foreign key(node) references nodes_legacy);\n");
485 printf("CREATE TABLE ways (id serial,username varchar(255), timestamp timestamptz);\n");
486 printf("CREATE TABLE way_tags (way integer, k varchar(255), v varchar(1024), primary key (way, k), foreign key(way) references ways);\n");
487 printf("CREATE TABLE way_nds (way integer, idx integer, to_node integer, foreign key(way) references ways, foreign key(to_node) references nodes_legacy, primary key(way, idx));\n");
488 printf("CREATE TABLE relations(id serial, username varchar(255), timestamp timestamptz);\n");
489 printf("CREATE TABLE relation_members_node (relation integer, idx integer, to_node integer, role varchar(255), foreign key(relation) references relations, foreign key(to_node) references nodes_legacy, primary key(relation, idx));\n");
490 printf("CREATE TABLE relation_members_relation (relation integer, idx integer, to_relation integer, role varchar(255), foreign key(relation) references relations, foreign key(to_relation) references relations, primary key(relation, idx));\n");
491 printf("CREATE TABLE relation_members_way (relation integer, idx integer, to_way integer, role varchar(255), foreign key(relation) references relations, foreign key(to_way) references ways, primary key(relation, idx));\n");
492 printf("CREATE TABLE relation_tags (relation integer, k varchar(255), v varchar(1024), foreign key(relation) references relations, primary key(relation, k));\n");
494 printf("COPY %lu RECORDS INTO nodes_legacy from '%s/" file_nodes
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
495 printf("COPY %lu RECORDS INTO nodes_legacy_uint from '%s/" file_nodes_uint
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
496 printf("COPY %lu RECORDS INTO nodes_legacy_gis from '%s/" file_nodes_gis
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
497 printf("COPY %lu RECORDS INTO node_tags from '%s/" file_node_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_node_tags
, current
);
498 printf("COPY %lu RECORDS INTO ways from '%s/" file_ways
"' USING DELIMITERS ',', '\\n', '''';\n", count_ways
, current
);
499 printf("COPY %lu RECORDS INTO way_tags from '%s/" file_way_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_tags
, current
);
500 printf("COPY %lu RECORDS INTO way_nds from '%s/" file_way_nds
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_nds
, current
);
501 printf("COPY %lu RECORDS INTO relations from '%s/" file_relations
"' USING DELIMITERS ',', '\\n', '''';\n", count_relations
, current
);
502 printf("COPY %lu RECORDS INTO relation_tags from '%s/" file_relation_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_relation_tags
, current
);
503 printf("COPY %lu RECORDS INTO relation_members_node from '%s/" file_relation_member_node
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_node
, current
);
504 printf("COPY %lu RECORDS INTO relation_members_relation from '%s/" file_relation_member_relation
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_relation
, current
);
505 printf("COPY %lu RECORDS INTO relation_members_way from '%s/" file_relation_member_way
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_way
, current
);
513 int main(int argc
, char *argv
[]) {
520 fprintf(stderr
, "Analysing %s...\n", argv
[1]);
522 fd
= open(argv
[1], O_RDONLY
);
527 if (fstat (fd
, &statbuf
) == -1) { perror("fstat:"); exit(-1); }
529 if (statbuf
.st_size
> 0) {
531 range
= mmap(NULL
, statbuf
.st_size
, PROT_READ
, MAP_SHARED
, fd
, (off_t
) 0);
532 if (range
== MAP_FAILED
) { perror("Mmap:"); printf("(did you compile PAE in the kernel?)\n"); exit(-1); }
533 parser(range
, statbuf
.st_size
/ sizeof(char));
534 munmap(range
, statbuf
.st_size
);