15 * <tag k=".." v=".." />
27 #define file_nodes "nodes.csv"
28 #define file_node_tags "node_tags.csv"
29 #define file_ways "ways.csv"
30 #define file_way_tags "way_tags.csv"
31 #define file_way_nds "way_nds.csv"
32 #define file_relations "relations.csv"
33 #define file_relation_tags "relation_tags.csv"
34 #define file_relation_member_node "relation_member_node.csv"
35 #define file_relation_member_relation "relation_member_relation.csv"
36 #define file_relation_member_way "relation_member_way.csv"
38 char * escape_string(char *instr
)
40 unsigned int i
, j
=0, need
= 0;
41 unsigned int len
= strlen(instr
);
45 if (instr
[i
]=='\\' || instr
[i
]=='\'') need
++;
48 outstr
= malloc(len
+ 1);
50 for (i
=0;i
<=strlen(instr
);i
++) {
51 if (instr
[i
]=='\\' || instr
[i
]=='\'')
59 static void parser(char *range
, unsigned long int max
) {
60 typedef enum { OSM
= 0, NODE
= 1, WAY
= 2, RELATION
= 3, TAG
= 4, ND
= 5, MEMBER
= 6 } osm_state_t
;
61 typedef enum { UNKNOWN
= 0, ID
, LAT
, LON
, USER
, TIMESTAMP
, KEY
, VALUE
, TYPE
, REF
, ROLE
} key_state_t
;
62 char *attr_id
= NULL
, *attr_lat
= NULL
, *attr_lon
= NULL
, *attr_user
= NULL
, *attr_timestamp
= NULL
, *attr_key
= NULL
, *attr_value
= NULL
,
63 *attr_type
= NULL
, *attr_ref
= NULL
, *attr_role
= NULL
;
65 FILE *fd_nodes
= fopen(file_nodes
, "w");
66 if (fd_nodes
== NULL
) { perror("Open:"); exit(-1); }
67 FILE *fd_node_tags
= fopen(file_node_tags
, "w");
68 if (fd_node_tags
== NULL
) { perror("Open:"); exit(-1); }
69 FILE *fd_ways
= fopen(file_ways
, "w");
70 if (fd_ways
== NULL
) { perror("Open:"); exit(-1); }
71 FILE *fd_way_tags
= fopen(file_way_tags
, "w");
72 if (fd_way_tags
== NULL
) { perror("Open:"); exit(-1); }
73 FILE *fd_way_nds
= fopen(file_way_nds
, "w");
74 if (fd_way_nds
== NULL
) { perror("Open:"); exit(-1); }
75 FILE *fd_relations
= fopen(file_relations
, "w");
76 if (fd_relations
== NULL
) { perror("Open:"); exit(-1); }
77 FILE *fd_relation_tags
= fopen(file_relation_tags
, "w");
78 if (fd_relation_tags
== NULL
) { perror("Open:"); exit(-1); }
79 FILE *fd_members_node
= fopen(file_relation_member_node
, "w");
80 if (fd_members_node
== NULL
) { perror("Open:"); exit(-1); }
81 FILE *fd_members_relation
= fopen(file_relation_member_relation
, "w");
82 if (fd_members_relation
== NULL
) { perror("Open:"); exit(-1); }
83 FILE *fd_members_way
= fopen(file_relation_member_way
, "w");
84 if (fd_members_way
== NULL
) { perror("Open:"); exit(-1); }
86 unsigned long int count_nodes
= 0, count_node_tags
= 0,
87 count_ways
= 0, count_way_tags
= 0, count_way_nds
= 0,
88 count_relations
= 0, count_relation_tags
= 0, count_members_node
= 0, count_members_relation
= 0, count_members_way
= 0;
90 unsigned long int sequence
= 0;
93 osm_state_t current_tag
= OSM
;
94 osm_state_t parent_tag
= OSM
;
96 char *start
, *end
, *nodename
, *nodename_end
;
99 end
= strchrnul((const char*) start
, '\n');
101 if (strncmp(start
, "<?xml", 5) != 0)
105 end
= strchrnul((const char*) start
, '\n');
107 if (strncmp(start
, "<osm", 4) != 0)
113 end
= strchrnul((const char*) start
, '\n');
115 nodename
= strchrnul(start
, '<') + 1;
116 nodename_end
= strchrnul(nodename
, ' ');
118 if (nodename
[0] == '/') {
122 free(attr_timestamp
);
129 attr_timestamp
= NULL
;
137 switch (nodename_end
- nodename
) {
142 switch (nodename
[0]) {
153 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
161 current_tag
= MEMBER
;
164 current_tag
= RELATION
;
167 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
171 char *key
, *key_end
, *value_end
;
172 key
= nodename_end
+ 1;
176 key_state_t current_key
= UNKNOWN
;
177 key_end
= strchrnul(key
, '=');
179 if (key_end
== NULL
|| key_end
>= end
)
182 switch (key_end
- key
) {
192 current_key
= UNKNOWN
;
211 current_key
= UNKNOWN
;
212 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
228 current_key
= UNKNOWN
;
229 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
234 current_key
= TIMESTAMP
;
237 char *thingie
= strndup(key
, (key_end
- key
));
238 current_key
= UNKNOWN
;
240 fprintf(stderr
, "UNKNOWN ATTR %s-> %c%c\n", thingie
, key
[0], key
[1]);
247 value_end
= strchr(value_end
, '"');
252 switch (current_key
) {
254 if (attr_id
) free(attr_id
);
255 attr_id
= strndup(value
, (value_end
- value
));
259 if (attr_lat
) free(attr_lat
);
260 attr_lat
= strndup(value
, (value_end
- value
));
264 if (attr_lon
) free(attr_lon
);
265 attr_lon
= strndup(value
, (value_end
- value
));
269 if (attr_timestamp
) free(attr_timestamp
);
270 attr_timestamp
= strndup(value
, (value_end
- value
));
271 // attr_timestamp[10] = ' '; /* Stupid timestamp fix */
276 if (attr_user
) free(attr_user
);
277 attr_user
= strndup(value
, (value_end
- value
));
278 tmp
= escape_string(attr_user
);
286 if (attr_key
) free(attr_key
);
287 attr_key
= strndup(value
, (value_end
- value
));
288 tmp
= escape_string(attr_key
);
296 if (attr_value
) free(attr_value
);
297 attr_value
= strndup(value
, (value_end
- value
));
298 tmp
= escape_string(attr_value
);
305 if (attr_type
) free(attr_type
);
306 attr_type
= strndup(value
, (value_end
- value
));
310 if (attr_ref
) free(attr_ref
);
311 attr_ref
= strndup(value
, (value_end
- value
));
316 if (attr_role
) free(attr_role
);
317 attr_role
= strndup(value
, (value_end
- value
));
318 tmp
= escape_string(attr_role
);
325 fprintf(stderr
, "--> %c%c\n", value
[0], value
[1]);
331 switch (current_tag
) {
333 fprintf(fd_nodes
, "%s, %s, %s, '%s', %s\n", attr_id
, attr_lat
, attr_lon
, attr_user
, attr_timestamp
);
337 switch (parent_tag
) {
339 fprintf(fd_node_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
343 fprintf(fd_way_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
347 fprintf(fd_relation_tags
, "%s, '%s', '%s'\n", attr_id
, attr_key
, attr_value
);
348 count_relation_tags
++;
356 fprintf(fd_ways
, "%s, '%s', '%s'\n", attr_id
, attr_user
, attr_timestamp
);
358 // fprintf(fd_way_tags, "%s, '%s', '%s'\n", attr_id, "type", "way");
362 fprintf(fd_relations
, "%s, '%s', '%s'\n", attr_id
, attr_user
, attr_timestamp
);
366 if (strcmp(attr_type
, "node") == 0) {
367 fprintf(fd_members_node
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
368 count_members_node
++;
369 } else if (strcmp(attr_type
, "way") == 0) {
370 fprintf(fd_members_way
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
372 } else if (strcmp(attr_type
, "relation") == 0) {
373 fprintf(fd_members_relation
, "%s, %lu, %s, '%s'\n", attr_id
, sequence
, attr_ref
, attr_role
);
374 count_members_relation
++;
379 fprintf(fd_way_nds
, "%s, %lu, %s\n", attr_id
, sequence
, attr_ref
);
387 if (end
[-2] == '/') {
388 switch (current_tag
) {
399 free(attr_timestamp
);
404 attr_timestamp
= NULL
;
429 } else if (current_tag
== NODE
|| current_tag
== WAY
|| current_tag
== RELATION
) {
430 parent_tag
= current_tag
;
433 } while ((start
= ++end
) < (range
+ max
));
438 free(attr_timestamp
);
445 fclose(fd_node_tags
);
449 fclose(fd_relations
);
450 fclose(fd_relation_tags
);
451 fclose(fd_members_node
);
452 fclose(fd_members_relation
);
454 char *current
= get_current_dir_name();
456 printf("START TRANSACTION;\n");
458 printf("CREATE TABLE nodes_legacy (id serial, x double, y double, username varchar(255), timestamp timestamptz);\n");
459 printf("CREATE TABLE node_tags (node integer, k varchar(255), v varchar(1024), primary key (node, k), foreign key(node) references nodes_legacy);\n");
460 printf("CREATE TABLE ways (id serial,username varchar(255), timestamp timestamptz);\n");
461 printf("CREATE TABLE way_tags (way integer, k varchar(255), v varchar(1024), primary key (way, k), foreign key(way) references ways);\n");
462 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");
463 printf("CREATE TABLE relations(id serial, username varchar(255), timestamp timestamptz);\n");
464 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");
465 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");
466 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");
467 printf("CREATE TABLE relation_tags (relation integer, k varchar(255), v varchar(1024), foreign key(relation) references relations, primary key(relation, k));\n");
469 printf("COPY %lu RECORDS INTO nodes_legacy from '%s/" file_nodes
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
470 printf("COPY %lu RECORDS INTO node_tags from '%s/" file_node_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_node_tags
, current
);
471 printf("COPY %lu RECORDS INTO ways from '%s/" file_ways
"' USING DELIMITERS ',', '\\n', '''';\n", count_ways
, current
);
472 printf("COPY %lu RECORDS INTO way_tags from '%s/" file_way_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_tags
, current
);
473 printf("COPY %lu RECORDS INTO way_nds from '%s/" file_way_nds
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_nds
, current
);
474 printf("COPY %lu RECORDS INTO relations from '%s/" file_relations
"' USING DELIMITERS ',', '\\n', '''';\n", count_relations
, current
);
475 printf("COPY %lu RECORDS INTO relation_tags from '%s/" file_relation_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_relation_tags
, current
);
476 printf("COPY %lu RECORDS INTO relation_members_node from '%s/" file_relation_member_node
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_node
, current
);
477 printf("COPY %lu RECORDS INTO relation_members_relation from '%s/" file_relation_member_relation
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_relation
, current
);
478 printf("COPY %lu RECORDS INTO relation_members_way from '%s/" file_relation_member_way
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_way
, current
);
486 int main(int argc
, char *argv
[]) {
493 fprintf(stderr
, "Analysing %s...\n", argv
[1]);
495 fd
= open(argv
[1], O_RDONLY
);
500 if (fstat (fd
, &statbuf
) == -1) { perror("fstat:"); exit(-1); }
502 if (statbuf
.st_size
> 0) {
504 range
= mmap(NULL
, statbuf
.st_size
, PROT_READ
, MAP_SHARED
, fd
, (off_t
) 0);
505 if (range
== MAP_FAILED
) { perror("Mmap:"); printf("(did you compile PAE in the kernel?)\n"); exit(-1); }
506 parser(range
, statbuf
.st_size
/ sizeof(char));
507 munmap(range
, statbuf
.st_size
);