summaryrefslogtreecommitdiff
path: root/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'info.c')
-rw-r--r--info.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/info.c b/info.c
new file mode 100644
index 0000000..19a537b
--- /dev/null
+++ b/info.c
@@ -0,0 +1,273 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+typedef struct Coord Coord;
+typedef struct BBox BBox;
+typedef struct MFHeader MFHeader;
+typedef struct Tag Tag;
+
+struct Coord {
+ double lat;
+ double lon;
+};
+
+struct BBox {
+ Coord min;
+ Coord max;
+};
+
+struct Tag {
+ int key;
+ char *val;
+};
+
+struct MFHeader {
+ char magic[21]; /* magic sequence */
+ uint size; /* header size */
+ uint fversion; /* file version */
+ uvlong fsize; /* file size */
+ uvlong dob; /* date of creation */
+ BBox bbox; /* map boundaries */
+ ushort tsize; /* tile size */
+ char *projection; /* Mercator or nothing */
+ uchar flags;
+ Coord pos0; /* map initial position */
+ uchar zoom0; /* map initial zoom level */
+ char *lang; /* language preference */
+ char *comment;
+ char *author;
+ Tag *pois; /* places of interest */
+ Tag *ways; /* ways */
+};
+
+enum {
+ Fdebug = 0x80,
+ Fpos0 = 0x40,
+ Fzoom0 = 0x20,
+ Flang = 0x10,
+ Fcomment = 0x08,
+ Fauthor = 0x04
+};
+
+void
+usage(void)
+{
+ fprint(2, "usage: info [mapfile]\n");
+ exits("usage");
+}
+
+ushort
+get16(uchar *a)
+{
+ return (a[0]<<8) | a[1];
+}
+
+uint
+get32(uchar *a)
+{
+ return (a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3];
+}
+
+uvlong
+get64(uchar *a)
+{
+ uvlong n;
+
+ n = get32(a);
+ return n<<32 | get32(a+4);
+}
+
+uint
+readuvarint(Biobuf *b)
+{
+ uint n, shift;
+ uchar x;
+
+ n = shift = 0;
+
+ if(Bread(b, &x, 1) != 1)
+ sysfatal("readuvarint: %r");
+ while(x & 0x80){
+ n |= (x & ~0x80) << shift;
+ shift += 7;
+ Bread(b, &x, 1);
+ }
+ return n |= x;
+}
+
+char *
+readstr(Biobuf *b)
+{
+ uint len;
+ char *s;
+
+ len = readuvarint(b);
+ s = malloc(len+1);
+ if(Bread(b, s, len) != len)
+ sysfatal("readstr: %r");
+ s[len] = 0;
+
+ return s;
+}
+
+double
+todeg(long μd)
+{
+ double d;
+ d = μd / 1000000.;
+ return d;
+}
+
+Coord
+getcoord(uchar *a)
+{
+ Coord c;
+ uchar *s;
+
+ s = a;
+ c.lat = todeg(get32(s));
+ s += 4;
+ c.lon = todeg(get32(s));
+
+ return c;
+}
+
+BBox
+getbbox(uchar *a)
+{
+ BBox bbox;
+ uchar *s;
+
+ s = a;
+ bbox.min = getcoord(s);
+ s += 8;
+ bbox.max = getcoord(s);
+
+ return bbox;
+}
+
+Tag *
+gettags(Biobuf *b)
+{
+ Tag *t;
+ uchar x[2];
+ int len, i;
+
+ if(Bread(b, x, 2) != 2)
+ sysfatal("gettags: %r");
+ len = get16(x);
+ t = malloc((len+1)*sizeof(Tag));
+ for(i = 0; i < len; i++)
+ t[i].val = readstr(b);
+ t[len].val = nil;
+
+ return t;
+}
+
+void
+main(int argc, char *argv[])
+{
+ Biobuf bin;
+ Tag *tp;
+ uchar buf[512];
+ int fd;
+
+ MFHeader h;
+
+ if(argc < 2)
+ fd = 0;
+ else{
+ fd = open(argv[1], OREAD);
+ if(fd < 0)
+ sysfatal("open: %r");
+ }
+
+ if(Binit(&bin, fd, OREAD) < 0)
+ sysfatal("Binit: %r");
+
+ if(Bread(&bin, buf, 20) != 20)
+ sysfatal("wrong magic value");
+ strncpy(h.magic, (char *)buf, 20);
+ h.magic[20] = 0;
+
+ if(Bread(&bin, buf, 4) != 4)
+ sysfatal("couldn't read header size");
+ h.size = get32(buf);
+
+ if(Bread(&bin, buf, 4) != 4)
+ sysfatal("couldn't read file version");
+ h.fversion = get32(buf);
+
+ if(Bread(&bin, buf, 8) != 8)
+ sysfatal("couldn't get file size");
+ h.fsize = get64(buf);
+
+ if(Bread(&bin, buf, 8) != 8)
+ sysfatal("couldn't get date of creation");
+ h.dob = get64(buf);
+
+ if(Bread(&bin, buf, 16) != 16)
+ sysfatal("couldn't get bbox");
+ h.bbox = getbbox(buf);
+
+ if(Bread(&bin, buf, 2) != 2)
+ sysfatal("couldn't get tile size");
+ h.tsize = get16(buf);
+
+ h.projection = readstr(&bin);
+
+ if(Bread(&bin, &h.flags, 1) != 1)
+ sysfatal("couldn't get flags");
+ if(h.flags & Fpos0){
+ if(Bread(&bin, buf, 8) != 8)
+ sysfatal("couldn't get pos0");
+ h.pos0 = getcoord(buf);
+ }
+ if(h.flags & Fzoom0)
+ Bread(&bin, &h.zoom0, 1);
+ if(h.flags & Flang)
+ h.lang = readstr(&bin);
+ if(h.flags & Fcomment)
+ h.comment = readstr(&bin);
+ if(h.flags & Fauthor)
+ h.author = readstr(&bin);
+ h.pois = gettags(&bin);
+ h.ways = gettags(&bin);
+
+ Bterm(&bin);
+
+ print("Mapsforge Header Information\n");
+ print("magic: %s\n", h.magic);
+ print("header size: %d bytes\n", h.size);
+ print("version: %d\n", h.fversion);
+ print("file size: %llud bytes\n", h.fsize);
+ print("created: %s", ctime(h.dob));
+ print("bbox: (%g°N, %g°E)(%g°N, %g°E)\n",
+ h.bbox.min.lat, h.bbox.min.lon,
+ h.bbox.max.lat, h.bbox.max.lon);
+ print("tile size: %d\n", h.tsize);
+ print("projection: %s\n", h.projection);
+ print("flags:");
+ if(h.flags & Fdebug) print(" debug");
+ if(h.flags & Fpos0) print(" pos0");
+ if(h.flags & Fzoom0) print(" zoom0");
+ if(h.flags & Flang) print(" lang");
+ if(h.flags & Fcomment) print(" comment");
+ if(h.flags & Fauthor) print(" author");
+ print("\n");
+ if(h.flags & Fpos0) print("pos0: (%g°N, %g°E)\n", h.pos0.lat, h.pos0.lon);
+ if(h.flags & Fzoom0) print("zoom0: %d\n", h.zoom0);
+ if(h.flags & Flang) print("lang: %s\n", h.lang);
+ if(h.flags & Fcomment) print("comment: %s\n", h.comment);
+ if(h.flags & Fauthor) print("author: %s\n", h.author);
+ print("pois:\n");
+ for(tp = h.pois; tp->val != nil; tp++)
+ print("\t%s\n", tp->val);
+ print("ways:\n");
+ for(tp = h.ways; tp->val != nil; tp++)
+ print("\t%s\n", tp->val);
+
+ close(fd);
+ exits(0);
+}