From 4c807a5ae20a98a2754af3c7345f6f5d97a39e78 Mon Sep 17 00:00:00 2001 From: martin-s Date: Sat, 11 Aug 2007 08:02:47 +0000 Subject: [PATCH] Moved poi_geodownload to data and made it working with the new api git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@379 ffa7fe5e-494d-0410-b361-a75ebd5db220 --- navit/configure.in | 2 + navit/src/attr.c | 46 ++ navit/src/attr.h | 3 + navit/src/attr_def.h | 1 + navit/src/country.c | 1 - navit/src/data/Makefile.am | 2 +- navit/src/data/mg/map.c | 4 +- navit/src/data/mg/mg.h | 2 +- navit/src/data/poi_geodownload/Makefile.am | 6 + navit/src/data/poi_geodownload/libmdb/Makefile.am | 13 + navit/src/data/poi_geodownload/libmdb/backend.c | 301 +++++++ navit/src/data/poi_geodownload/libmdb/catalog.c | 138 ++++ navit/src/data/poi_geodownload/libmdb/data.c | 856 +++++++++++++++++++ navit/src/data/poi_geodownload/libmdb/dump.c | 39 + navit/src/data/poi_geodownload/libmdb/file.c | 376 +++++++++ navit/src/data/poi_geodownload/libmdb/iconv.c | 63 ++ .../data/poi_geodownload/libmdb/include/mdbtools.h | 536 ++++++++++++ navit/src/data/poi_geodownload/libmdb/index.c | 905 +++++++++++++++++++++ navit/src/data/poi_geodownload/libmdb/kkd.c | 149 ++++ navit/src/data/poi_geodownload/libmdb/like.c | 78 ++ navit/src/data/poi_geodownload/libmdb/map.c | 133 +++ navit/src/data/poi_geodownload/libmdb/mem.c | 50 ++ navit/src/data/poi_geodownload/libmdb/money.c | 139 ++++ navit/src/data/poi_geodownload/libmdb/options.c | 86 ++ navit/src/data/poi_geodownload/libmdb/props.c | 127 +++ navit/src/data/poi_geodownload/libmdb/sargs.c | 273 +++++++ navit/src/data/poi_geodownload/libmdb/stats.c | 74 ++ navit/src/data/poi_geodownload/libmdb/table.c | 368 +++++++++ navit/src/data/poi_geodownload/libmdb/worktable.c | 99 +++ navit/src/data/poi_geodownload/libmdb/write.c | 878 ++++++++++++++++++++ navit/src/data/poi_geodownload/poi_geodownload.c | 661 +++++++++++++++ navit/src/data/textfile/textfile.c | 2 +- navit/src/graphics.c | 4 +- navit/src/gui/gtk/destination.c | 3 +- navit/src/item.c | 1 - navit/src/item.h | 3 +- navit/src/item_def.h | 4 + navit/src/map.c | 6 +- navit/src/map.h | 2 +- navit/src/mapset.c | 2 +- navit/src/navit.c | 2 +- navit/src/plugin_def.h | 3 +- navit/src/search.c | 1 - navit/src/xmlconfig.c | 31 +- 44 files changed, 6453 insertions(+), 20 deletions(-) create mode 100644 navit/src/data/poi_geodownload/Makefile.am create mode 100644 navit/src/data/poi_geodownload/libmdb/Makefile.am create mode 100644 navit/src/data/poi_geodownload/libmdb/backend.c create mode 100644 navit/src/data/poi_geodownload/libmdb/catalog.c create mode 100644 navit/src/data/poi_geodownload/libmdb/data.c create mode 100644 navit/src/data/poi_geodownload/libmdb/dump.c create mode 100644 navit/src/data/poi_geodownload/libmdb/file.c create mode 100644 navit/src/data/poi_geodownload/libmdb/iconv.c create mode 100644 navit/src/data/poi_geodownload/libmdb/include/mdbtools.h create mode 100644 navit/src/data/poi_geodownload/libmdb/index.c create mode 100644 navit/src/data/poi_geodownload/libmdb/kkd.c create mode 100644 navit/src/data/poi_geodownload/libmdb/like.c create mode 100644 navit/src/data/poi_geodownload/libmdb/map.c create mode 100644 navit/src/data/poi_geodownload/libmdb/mem.c create mode 100644 navit/src/data/poi_geodownload/libmdb/money.c create mode 100644 navit/src/data/poi_geodownload/libmdb/options.c create mode 100644 navit/src/data/poi_geodownload/libmdb/props.c create mode 100644 navit/src/data/poi_geodownload/libmdb/sargs.c create mode 100644 navit/src/data/poi_geodownload/libmdb/stats.c create mode 100644 navit/src/data/poi_geodownload/libmdb/table.c create mode 100644 navit/src/data/poi_geodownload/libmdb/worktable.c create mode 100644 navit/src/data/poi_geodownload/libmdb/write.c create mode 100644 navit/src/data/poi_geodownload/poi_geodownload.c diff --git a/navit/configure.in b/navit/configure.in index 9abaac7..8b96e91 100644 --- a/navit/configure.in +++ b/navit/configure.in @@ -253,6 +253,8 @@ src/data/Makefile src/data/mg/Makefile src/data/textfile/Makefile src/data/garmin_img/Makefile +src/data/poi_geodownload/Makefile +src/data/poi_geodownload/libmdb/Makefile src/fib-1.1/Makefile src/graphics/Makefile src/graphics/gtk_drawing_area/Makefile diff --git a/navit/src/attr.c b/navit/src/attr.c index 0c6d58a..91d3f5a 100644 --- a/navit/src/attr.c +++ b/navit/src/attr.c @@ -1,4 +1,7 @@ #include +#include +#include "debug.h" +#include "item.h" #include "attr.h" struct attr_name { @@ -38,3 +41,46 @@ attr_to_name(enum attr_type attr) } return NULL; } + +struct attr * +attr_new_from_text(char *name, char *value) +{ + enum attr_type attr; + struct attr *ret; + + ret=g_new0(struct attr, 1); + dbg(0,"enter name='%s' value='%s'\n", name, value); + attr=attr_from_name(name); + ret->type=attr; + switch (attr) { + case attr_item_type: + ret->u.item_type=item_from_name(value); + break; + default: + dbg(0,"default\n"); + g_free(ret); + ret=NULL; + } + return ret; +} + +struct attr * +attr_search(struct attr **attrs, struct attr *last, enum attr_type attr) +{ + dbg(0, "enter attrs=%p\n", attrs); + while (*attrs) { + dbg(0,"*attrs=%p\n", *attrs); + if ((*attrs)->type == attr) { + return *attrs; + } + attrs++; + } + exit(0); + return NULL; +} + +void +attr_free(struct attr *attr) +{ + g_free(attr); +} diff --git a/navit/src/attr.h b/navit/src/attr.h index 83a12f5..356185c 100644 --- a/navit/src/attr.h +++ b/navit/src/attr.h @@ -1,6 +1,8 @@ #ifndef ATTR_H #define ATTR_H +enum item_type; + enum attr_type { #define ATTR2(x,y) attr_##x=y, #define ATTR(x) attr_##x, @@ -15,6 +17,7 @@ struct attr { char *str; int num; struct item *item; + enum item_type item_type; } u; }; diff --git a/navit/src/attr_def.h b/navit/src/attr_def.h index 1a2d472..0f25976 100644 --- a/navit/src/attr_def.h +++ b/navit/src/attr_def.h @@ -7,6 +7,7 @@ ATTR(street_name_item) ATTR(street_name_numbers_item) ATTR(street_item) ATTR(street_number_item) +ATTR(item_type) ATTR2(type_item_end,0x0001ffff) ATTR2(type_int_begin,0x00020000) ATTR(id) diff --git a/navit/src/country.c b/navit/src/country.c index 42864da..f7f238f 100644 --- a/navit/src/country.c +++ b/navit/src/country.c @@ -3,7 +3,6 @@ #include #include #include "debug.h" -#include "attr.h" #include "item.h" #include "country.h" #include "search.h" diff --git a/navit/src/data/Makefile.am b/navit/src/data/Makefile.am index 35a1135..8f7999b 100644 --- a/navit/src/data/Makefile.am +++ b/navit/src/data/Makefile.am @@ -1 +1 @@ -SUBDIRS=mg textfile garmin_img +SUBDIRS=mg textfile garmin_img poi_geodownload diff --git a/navit/src/data/mg/map.c b/navit/src/data/mg/map.c index 20feb8f..6122b98 100644 --- a/navit/src/data/mg/map.c +++ b/navit/src/data/mg/map.c @@ -7,7 +7,7 @@ #include "mg.h" -struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro); +struct map_priv * map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro); static int map_id; @@ -259,7 +259,7 @@ static struct map_methods map_methods_mg = { }; struct map_priv * -map_new_mg(struct map_methods *meth, char *dirname, char **charset, enum projection *pro) +map_new_mg(struct map_methods *meth, char *dirname, struct attr **attrs, char **charset, enum projection *pro) { struct map_priv *m; int i,maybe_missing,len=strlen(dirname); diff --git a/navit/src/data/mg/mg.h b/navit/src/data/mg/mg.h index c94a536..78f72c0 100644 --- a/navit/src/data/mg/mg.h +++ b/navit/src/data/mg/mg.h @@ -1,8 +1,8 @@ #include +#include "item.h" #include "attr.h" #include "coord.h" #include "data.h" -#include "item.h" #include "map.h" #include "file.h" diff --git a/navit/src/data/poi_geodownload/Makefile.am b/navit/src/data/poi_geodownload/Makefile.am new file mode 100644 index 0000000..d3412df --- /dev/null +++ b/navit/src/data/poi_geodownload/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS=libmdb +include $(top_srcdir)/Makefile.inc +AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -Ilibmdb/include -DMODULE=\"data_poi_geodownload\" +moduledata_LTLIBRARIES = libdata_poi_geodownload.la +libdata_poi_geodownload_la_SOURCES = poi_geodownload.c +libdata_poi_geodownload_la_LIBADD = -Llibmdb -lmdb diff --git a/navit/src/data/poi_geodownload/libmdb/Makefile.am b/navit/src/data/poi_geodownload/libmdb/Makefile.am new file mode 100644 index 0000000..6ff3fd6 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/Makefile.am @@ -0,0 +1,13 @@ +AUTOMAKE_OPTIONS = no-exeext +AM_CPPFLAGS = @NAVIT_CFLAGS@ -Iinclude + +objdir=$(prefix) +obj_PROGRAMS=libmdb.a +INSTALL_PROGRAM=/bin/true + +libmdb_a_SOURCES=backend.c catalog.c data.c dump.c file.c iconv.c index.c kkd.c like.c map.c mem.c money.c options.c props.c sargs.c stats.c table.c worktable.c write.c + +libmdb.a: $(libmdb_a_OBJECTS) + ar r $@ $(libmdb_a_OBJECTS) + + diff --git a/navit/src/data/poi_geodownload/libmdb/backend.c b/navit/src/data/poi_geodownload/libmdb/backend.c new file mode 100644 index 0000000..e90f807 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/backend.c @@ -0,0 +1,301 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* +** functions to deal with different backend database engines +*/ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +static int is_init; +static GHashTable *mdb_backends; + + /* Access data types */ +static MdbBackendType mdb_access_types[] = { + {"Unknown 0x00", 0,0,0 }, + {"Boolean", 0,0,0}, + {"Byte", 0,0,0}, + {"Integer", 0,0,0}, + {"Long Integer", 0,0,0}, + {"Currency", 0,0,0}, + {"Single", 0,0,0}, + {"Double", 0,0,0}, + {"DateTime (Short)", 0,0,1}, + {"Unknown 0x09", 0,0,0}, + {"Text", 1,0,1}, + {"OLE", 1,0,1}, + {"Memo/Hyperlink",1,0,1}, + {"Unknown 0x0d",0,0,0}, + {"Unknown 0x0e",0,0,0}, + {"Replication ID",0,0,0}, + {"Numeric",1,1,0} +}; + +/* Oracle data types */ +static MdbBackendType mdb_oracle_types[] = { + {"Oracle_Unknown 0x00",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, + {"FLOAT",0,0,0}, + {"FLOAT",0,0,0}, + {"DATE",0,0,0}, + {"Oracle_Unknown 0x09",0,0,0}, + {"VARCHAR2",1,0,1}, + {"BLOB",1,0,1}, + {"CLOB",1,0,1}, + {"Oracle_Unknown 0x0d",0,0,0}, + {"Oracle_Unknown 0x0e",0,0,0}, + {"NUMBER",1,0,0}, + {"NUMBER",1,0,0}, +}; + +/* Sybase/MSSQL data types */ +static MdbBackendType mdb_sybase_types[] = { + {"Sybase_Unknown 0x00",0,0,0}, + {"bit",0,0,0}, + {"char",1,0,1}, + {"smallint",0,0,0}, + {"int",0,0,0}, + {"money",0,0,0}, + {"real",0,0,0}, + {"float",0,0,0}, + {"smalldatetime",0,0,0}, + {"Sybase_Unknown 0x09",0,0,0}, + {"varchar",1,0,1}, + {"varbinary",1,0,1}, + {"text",1,0,1}, + {"Sybase_Unknown 0x0d",0,0,0}, + {"Sybase_Unknown 0x0e",0,0,0}, + {"Sybase_Replication ID",0,0,0}, + {"numeric",1,1,0}, +}; + +/* Postgres data types */ +static MdbBackendType mdb_postgres_types[] = { + {"Postgres_Unknown 0x00",0,0,0}, + {"Bool",0,0,0}, + {"Int2",0,0,0}, + {"Int4",0,0,0}, + {"Int8",0,0,0}, + {"Money",0,0,0}, + {"Float4",0,0,0}, + {"Float8",0,0,0}, + {"Timestamp",0,0,0}, + {"Postgres_Unknown 0x09",0,0,0}, + {"Char",1,0,1}, + {"Postgres_Unknown 0x0b",0,0,0}, + {"Postgres_Unknown 0x0c",0,0,0}, + {"Postgres_Unknown 0x0d",0,0,0}, + {"Postgres_Unknown 0x0e",0,0,0}, + {"Serial",0,0,0}, + {"Postgres_Unknown 0x10",0,0,0}, +}; +/* MySQL data types */ +static MdbBackendType mdb_mysql_types[] = { + {"Text",1,0,1}, + {"char",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"int",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"float",0,0,0}, + {"date",0,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"varchar",1,0,1}, + {"text",1,0,1}, + {"blob",0,0,0}, + {"text",1,0,1}, + {"numeric",1,1,0}, + {"numeric",1,1,0}, +}; + +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data); + +char *mdb_get_coltype_string(MdbBackend *backend, int col_type) +{ + static char buf[16]; + + if (col_type > 0x10 ) { + // return NULL; + snprintf(buf,sizeof(buf), "type %04x", col_type); + return buf; + } else { + return backend->types_table[col_type].name; + } +} + +int mdb_coltype_takes_length(MdbBackend *backend, int col_type) +{ + return backend->types_table[col_type].needs_length; +} + +/** + * mdb_init_backends + * + * Initializes the mdb_backends hash and loads the builtin backends. + * Use mdb_remove_backends() to destroy this hash when done. + */ +void mdb_init_backends() +{ + mdb_backends = g_hash_table_new(g_str_hash, g_str_equal); + + mdb_register_backend(mdb_access_types, "access"); + mdb_register_backend(mdb_sybase_types, "sybase"); + mdb_register_backend(mdb_oracle_types, "oracle"); + mdb_register_backend(mdb_postgres_types, "postgres"); + mdb_register_backend(mdb_mysql_types, "mysql"); +} +void mdb_register_backend(MdbBackendType *backend_type, char *backend_name) +{ + MdbBackend *backend = (MdbBackend *) g_malloc0(sizeof(MdbBackend)); + backend->types_table = backend_type; + g_hash_table_insert(mdb_backends, backend_name, backend); +} + +/** + * mdb_remove_backends + * + * Removes all entries from and destroys the mdb_backends hash. + */ +void mdb_remove_backends() +{ + g_hash_table_foreach_remove(mdb_backends, mdb_drop_backend, NULL); + g_hash_table_destroy(mdb_backends); +} +static gboolean mdb_drop_backend(gpointer key, gpointer value, gpointer data) +{ + MdbBackend *backend = (MdbBackend *)value; + g_free (backend); + return TRUE; +} + +/** + * mdb_set_default_backend + * @mdb: Handle to open MDB database file + * @backend_name: Name of the backend to set as default + * + * Sets the default backend of the handle @mdb to @backend_name. + * + * Returns: 1 if successful, 0 if unsuccessful. + */ +int mdb_set_default_backend(MdbHandle *mdb, char *backend_name) +{ + MdbBackend *backend; + + backend = (MdbBackend *) g_hash_table_lookup(mdb_backends, backend_name); + if (backend) { + mdb->default_backend = backend; + mdb->backend_name = (char *) g_strdup(backend_name); + is_init = 0; + return 1; + } else { + return 0; + } +} + +/** + * mdb_get_relationships + * @mdb: Handle to open MDB database file + * + * Generates relationships by reading the MSysRelationships table. + * 'szColumn' contains the column name of the child table. + * 'szObject' contains the table name of the child table. + * 'szReferencedColumn' contains the column name of the parent table. + * 'szReferencedObject' contains the table name of the parent table. + * + * Returns: a string stating that relationships are not supported for the + * selected backend, or a string containing SQL commands for setting up + * the relationship, tailored for the selected backend. The caller is + * responsible for freeing this string. + */ +char *mdb_get_relationships(MdbHandle *mdb) +{ + unsigned int i; + gchar *text = NULL; /* String to be returned */ + static char *bound[4]; /* Bound values */ + static MdbTableDef *table; /* Relationships table */ + int backend = 0; /* Backends: 1=oracle */ + + if (strncmp(mdb->backend_name,"oracle",6) == 0) { + backend = 1; + } else { + if (is_init == 0) { /* the first time through */ + is_init = 1; + return (char *) g_strconcat( + "-- relationships are not supported for ", + mdb->backend_name, NULL); + } else { /* the second time through */ + is_init = 0; + return NULL; + } + } + + if (is_init == 0) { + table = mdb_read_table_by_name(mdb, "MSysRelationships", MDB_TABLE); + if ((!table) || (table->num_rows == 0)) { + return NULL; + } + + mdb_read_columns(table); + for (i=0;i<4;i++) { + bound[i] = (char *) g_malloc0(MDB_BIND_SIZE); + } + mdb_bind_column_by_name(table, "szColumn", bound[0]); + mdb_bind_column_by_name(table, "szObject", bound[1]); + mdb_bind_column_by_name(table, "szReferencedColumn", bound[2]); + mdb_bind_column_by_name(table, "szReferencedObject", bound[3]); + mdb_rewind_table(table); + + is_init = 1; + } + else if (table->cur_row >= table->num_rows) { /* past the last row */ + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + if (!mdb_fetch_row(table)) { + for (i=0;i<4;i++) + g_free(bound[i]); + is_init = 0; + return NULL; + } + + switch (backend) { + case 1: /* oracle */ + text = g_strconcat("alter table ", bound[1], + " add constraint ", bound[3], "_", bound[1], + " foreign key (", bound[0], ")" + " references ", bound[3], "(", bound[2], ")", NULL); + break; + } + + return (char *)text; +} + diff --git a/navit/src/data/poi_geodownload/libmdb/catalog.c b/navit/src/data/poi_geodownload/libmdb/catalog.c new file mode 100644 index 0000000..dc08abd --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/catalog.c @@ -0,0 +1,138 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +char * +mdb_get_objtype_string(int obj_type) +{ +static char *type_name[] = {"Form", + "Table", + "Macro", + "System Table", + "Report", + "Query", + "Linked Table", + "Module", + "Relationship", + "Unknown 0x09", + "Unknown 0x0a", + "Database" + }; + + if (obj_type > 11) { + return NULL; + } else { + return type_name[obj_type]; + } +} + +void mdb_free_catalog(MdbHandle *mdb) +{ + unsigned int i; + + if (!mdb->catalog) return; + for (i=0; icatalog->len; i++) + g_free (g_ptr_array_index(mdb->catalog, i)); + g_ptr_array_free(mdb->catalog, TRUE); + mdb->catalog = NULL; +} + +GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtype) +{ + MdbCatalogEntry *entry, msysobj; + MdbTableDef *table; + char obj_id[256]; + char obj_name[256]; + char obj_type[256]; + char obj_flags[256]; + int type; + + if (mdb->catalog) mdb_free_catalog(mdb); + mdb->catalog = g_ptr_array_new(); + mdb->num_catalog = 0; + + /* dummy up a catalog entry so we may read the table def */ + memset(&msysobj, 0, sizeof(MdbCatalogEntry)); + msysobj.mdb = mdb; + msysobj.object_type = MDB_TABLE; + msysobj.table_pg = 2; + strcpy(msysobj.object_name, "MSysObjects"); + + /* mdb_table_dump(&msysobj); */ + + table = mdb_read_table(&msysobj); + if (!table) return NULL; + + mdb_read_columns(table); + + mdb_bind_column_by_name(table, "Id", obj_id); + mdb_bind_column_by_name(table, "Name", obj_name); + mdb_bind_column_by_name(table, "Type", obj_type); + mdb_bind_column_by_name(table, "Flags", obj_flags); + + mdb_rewind_table(table); + + while (mdb_fetch_row(table)) { + type = atoi(obj_type); + if (objtype==MDB_ANY || type == objtype) { + // fprintf(stdout, "obj_id: %10ld objtype: %-3d obj_name: %s\n", + // (atol(obj_id) & 0x00FFFFFF), type, obj_name); + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + strcpy(entry->object_name, obj_name); + entry->object_type = (type & 0x7F); + entry->table_pg = atol(obj_id) & 0x00FFFFFF; + entry->flags = atol(obj_flags); + mdb->num_catalog++; + g_ptr_array_add(mdb->catalog, entry); + } + } + //mdb_dump_catalog(mdb, MDB_TABLE); + + mdb_free_tabledef(table); + + return mdb->catalog; +} + +void +mdb_dump_catalog(MdbHandle *mdb, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + if (obj_type==MDB_ANY || entry->object_type==obj_type) { + fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2d\n", + mdb_get_objtype_string(entry->object_type), + entry->object_name, + (unsigned int) entry->table_pg, + (unsigned int) entry->kkd_pg, + entry->kkd_rowid); + } + } + return; +} + diff --git a/navit/src/data/poi_geodownload/libmdb/data.c b/navit/src/data/poi_geodownload/libmdb/data.c new file mode 100644 index 0000000..e50e57d --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/data.c @@ -0,0 +1,856 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define OFFSET_MASK 0x1fff + +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s); +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, unsigned char isnull, int offset, int len); +static char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale); +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size); + +static char date_fmt[64] = "%x %X"; + +void mdb_set_date_fmt(const char *fmt) +{ + date_fmt[63] = 0; + strncpy(date_fmt, fmt, 63); +} + +void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr) +{ +MdbColumn *col; + + /* + ** the column arrary is 0 based, so decrement to get 1 based parameter + */ + col=g_ptr_array_index(table->columns, col_num - 1); + col->bind_ptr = bind_ptr; +} +int +mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr) +{ + unsigned int i; + int col_num = -1; + MdbColumn *col; + + for (i=0;inum_cols;i++) { + col=g_ptr_array_index(table->columns,i); + if (!strcmp(col->name,col_name)) { + col_num = col->col_num + 1; + mdb_bind_column(table, col_num, bind_ptr); + break; + } + } + + return col_num; +} +void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr) +{ +MdbColumn *col; + + col=g_ptr_array_index(table->columns, col_num - 1); + col->len_ptr = len_ptr; +} + +/** + * mdb_find_pg_row + * @mdb: Database file handle + * @pg_row: Lower byte contains the row number, the upper three contain page + * @buf: Pointer for returning a pointer to the page + * @off: Pointer for returning an offset to the row + * @len: Pointer for returning the length of the row + * + * Returns: 0 on success. 1 on failure. + */ +int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len) +{ + unsigned int pg = pg_row >> 8; + unsigned int row = pg_row & 0xff; + + if (mdb_read_alt_pg(mdb, pg) != mdb->fmt->pg_size) + return 1; + mdb_swap_pgbuf(mdb); + *off = mdb_pg_get_int16(mdb, mdb->fmt->row_count_offset + 2 + (row*2)); + *len = mdb_find_end_of_row(mdb, row) - *off + 1; + mdb_swap_pgbuf(mdb); + *buf = mdb->alt_pg_buf; + return 0; +} + +int +mdb_find_end_of_row(MdbHandle *mdb, int row) +{ + MdbFormatConstants *fmt = mdb->fmt; + int row_end; + + /* Search the previous "row start" values for the first non-'lookupflag' one. + * If we don't find one, then the end of the page is the correct value. + */ +#if 1 + if (row==0) { + row_end = fmt->pg_size - 1; + } else { + row_end = (mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + (row - 1) * 2)) & OFFSET_MASK) - 1; + } + return row_end; +#else + int i, row_start; + + /* if lookupflag is not set, it's good (deleteflag is ok) */ + for (i = row - 1; i >= 0; i--) { + row_start = mdb_pg_get_int16(mdb, ((fmt->row_count_offset + 2) + i * 2)); + if (!(row_start & 0x8000)) { + break; + } + } + + if (i == -1) { + row_end = fmt->pg_size - 1; + } else { + row_end = (row_start & OFFSET_MASK) - 1; + } + return row_end; +#endif +} +int mdb_is_null(unsigned char *null_mask, int col_num) +{ +int byte_num = (col_num - 1) / 8; +int bit_num = (col_num - 1) % 8; + + if ((1 << bit_num) & null_mask[byte_num]) { + return 0; + } else { + return 1; + } +} +/* bool has to be handled specially because it uses the null bit to store its +** value*/ +static int +mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value) +{ + + col->cur_value_len = value; + if (col->bind_ptr) { + strcpy(col->bind_ptr, value ? "0" : "1"); + } + + return 0; +} +static int mdb_xfer_bound_ole(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ + int ret = 0; + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr || col->len_ptr) { + //ret = mdb_copy_ole(mdb, col->bind_ptr, start, len); + memcpy(col->bind_ptr, &mdb->pg_buf[start], MDB_MEMO_OVERHEAD); + } + if (col->len_ptr) { + *col->len_ptr = MDB_MEMO_OVERHEAD; + } + return ret; +} +static int mdb_xfer_bound_data(MdbHandle *mdb, int start, MdbColumn *col, int len) +{ +int ret; + //if (!strcmp("Name",col->name)) { + //printf("start %d %d\n",start, len); + //} + if (len) { + col->cur_value_start = start; + col->cur_value_len = len; + } else { + col->cur_value_start = 0; + col->cur_value_len = 0; + } + if (col->bind_ptr) { + if (!len) { + strcpy(col->bind_ptr, ""); + } else if (col->col_type == MDB_NUMERIC) { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_num_to_string(mdb, start, col->col_type, + col->col_prec, col->col_scale); + strcpy(col->bind_ptr, str); + g_free(str); + } else { + //fprintf(stdout,"len %d size %d\n",len, col->col_size); + char *str = mdb_col_to_string(mdb, mdb->pg_buf, start, + col->col_type, len); + strcpy(col->bind_ptr, str); + + } + ret = strlen(col->bind_ptr); + if (col->len_ptr) { + *col->len_ptr = ret; + } + return ret; + } + return 0; +} +int mdb_read_row(MdbTableDef *table, unsigned int row) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *col; + unsigned int i; + int rc; + int row_start, row_end; + int delflag, lookupflag; + MdbField fields[256]; + int num_fields; + + if (table->num_rows <= row) + return 0; + + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2)); + row_end = mdb_find_end_of_row(mdb, row); + + delflag = lookupflag = 0; + if (row_start & 0x8000) lookupflag++; + if (row_start & 0x4000) delflag++; + row_start &= OFFSET_MASK; /* remove flags */ +#if MDB_DEBUG + fprintf(stdout,"Row %d bytes %d to %d %s %s\n", + row, row_start, row_end, + lookupflag ? "[lookup]" : "", + delflag ? "[delflag]" : ""); +#endif + + if (!table->noskip_del && delflag) { + row_end = row_start-1; + return 0; + } + + num_fields = mdb_crack_row(table, row_start, row_end, fields); + if (!mdb_test_sargs(table, fields, num_fields)) return 0; + +#if MDB_DEBUG + fprintf(stdout,"sarg test passed row %d \n", row); +#endif + +#if MDB_DEBUG + buffer_dump(mdb->pg_buf, row_start, row_end); +#endif + + /* take advantage of mdb_crack_row() to clean up binding */ + /* use num_cols instead of num_fields -- bsb 03/04/02 */ + for (i = 0; i < table->num_cols; i++) { + col = g_ptr_array_index(table->columns,fields[i].colnum); + rc = _mdb_attempt_bind(mdb, col, fields[i].is_null, + fields[i].start, fields[i].siz); + } + + return 1; +} +static int _mdb_attempt_bind(MdbHandle *mdb, + MdbColumn *col, + unsigned char isnull, + int offset, + int len) +{ + if (col->col_type == MDB_BOOL) { + mdb_xfer_bound_bool(mdb, col, isnull); + } else if (isnull) { + mdb_xfer_bound_data(mdb, 0, col, 0); + } else if (col->col_type == MDB_OLE) { + mdb_xfer_bound_ole(mdb, offset, col, len); + } else { + //if (!mdb_test_sargs(mdb, col, offset, len)) { + //return 0; + //} + mdb_xfer_bound_data(mdb, offset, col, len); + } + return 1; +} +int mdb_read_next_dpg(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int next_pg; + +#ifndef SLOW_READ + next_pg = mdb_map_find_next(mdb, table->usage_map, + table->map_sz, table->cur_phys_pg); + + if (next_pg >= 0) { + if (mdb_read_pg(mdb, next_pg)) { + table->cur_phys_pg = next_pg; + return table->cur_phys_pg; + } else { + return 0; + } + } + fprintf(stderr, "Warning: defaulting to brute force read\n"); +#endif + /* can't do a fast read, go back to the old way */ + do { + if (!mdb_read_pg(mdb, table->cur_phys_pg++)) + return 0; + } while (mdb->pg_buf[0]!=0x01 || mdb_pg_get_int32(mdb, 4)!=entry->table_pg); + /* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */ + return table->cur_phys_pg; +} +int mdb_rewind_table(MdbTableDef *table) +{ + table->cur_pg_num=0; + table->cur_phys_pg=0; + table->cur_row=0; + + return 0; +} +int +mdb_fetch_row(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + unsigned int rows; + int rc; + guint32 pg; + + if (table->num_rows==0) + return 0; + + /* initialize */ + if (!table->cur_pg_num) { + table->cur_pg_num=1; + table->cur_row=0; + if ((!table->is_temp_table)&&(table->strategy!=MDB_INDEX_SCAN)) + if (!mdb_read_next_dpg(table)) return 0; + } + + do { + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + rows = mdb_get_int16( + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->row_count_offset); + if (table->cur_row >= rows) { + table->cur_row = 0; + table->cur_pg_num++; + if (table->cur_pg_num > pages->len) + return 0; + } + memcpy(mdb->pg_buf, + g_ptr_array_index(pages, table->cur_pg_num-1), + fmt->pg_size); + } else if (table->strategy==MDB_INDEX_SCAN) { + + if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) { + mdb_index_scan_free(table); + return 0; + } + mdb_read_pg(mdb, pg); + } else { + rows = mdb_pg_get_int16(mdb,fmt->row_count_offset); + + /* if at end of page, find a new page */ + if (table->cur_row >= rows) { + table->cur_row=0; + + if (!mdb_read_next_dpg(table)) { + return 0; + } + } + } + + /* printf("page %d row %d\n",table->cur_phys_pg, table->cur_row); */ + rc = mdb_read_row(table, table->cur_row); + table->cur_row++; + } while (!rc); + + return 1; +} +void mdb_data_dump(MdbTableDef *table) +{ + unsigned int i; + char *bound_values[MDB_MAX_COLS]; + + for (i=0;inum_cols;i++) { + bound_values[i] = (char *) g_malloc(256); + mdb_bind_column(table, i+1, bound_values[i]); + } + mdb_rewind_table(table); + while (mdb_fetch_row(table)) { + for (i=0;inum_cols;i++) { + fprintf(stdout, "column %d is %s\n", i+1, bound_values[i]); + } + } + for (i=0;inum_cols;i++) { + g_free(bound_values[i]); + } +} + +int mdb_is_fixed_col(MdbColumn *col) +{ + return col->is_fixed; +} +#if 0 +static char *mdb_data_to_hex(MdbHandle *mdb, char *text, int start, int size) +{ +int i; + + for (i=start; ipg_buf[i]); + } + text[(i-start)*2]='\0'; + + return text; +} +#endif +int +mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + + if (ole_flags == 0x8000) { + /* inline fields don't have a next */ + return 0; + } else if (ole_flags == 0x4000) { + /* 0x4000 flagged ole's are contained on one page and thus + * should be handled entirely with mdb_ole_read() */ + return 0; + } else if (ole_flags == 0x0000) { + pg_row = (col->cur_blob_pg << 8) & col->cur_blob_row; + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } + return 0; +} +int +mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) +{ + guint16 ole_len; + guint16 ole_flags; + char *buf; + int pg_row, row_start; + int len; + + ole_len = mdb_get_int16(ole_ptr, 0); + ole_flags = mdb_get_int16(ole_ptr, 2); + mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %08x", + ole_len, ole_flags); + + col->chunk_size = chunk_size; + + if (ole_flags == 0x8000) { + /* inline ole field, if we can satisfy it, then do it */ + len = col->cur_value_len - MDB_MEMO_OVERHEAD; + if (chunk_size >= len) { + if (col->bind_ptr) + memcpy(col->bind_ptr, + &mdb->pg_buf[col->cur_value_start + + MDB_MEMO_OVERHEAD], + len); + return len; + } else { + return 0; + } + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %ld", + col->cur_blob_row, col->cur_blob_pg); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); + + if (col->bind_ptr) { + memcpy(col->bind_ptr, buf + row_start, len); + if (mdb_get_option(MDB_DEBUG_OLE)) + buffer_dump(col->bind_ptr, 0, 16); + } + return len; + } else if (ole_flags == 0x0000) { + pg_row = mdb_get_int32(ole_ptr, 4); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + + if (col->bind_ptr) + memcpy(col->bind_ptr, buf + row_start, len); + + pg_row = mdb_get_int32(buf, row_start); + col->cur_blob_pg = pg_row >> 8; + col->cur_blob_row = pg_row & 0xff; + + return len; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size) +{ + guint16 ole_len; + guint16 ole_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + return len; + } else if (ole_flags == 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest, buf + row_start, len); + return len; + } else if (ole_flags == 0x0000) { + int cur = 0; + pg_row = mdb_get_int32(mdb->pg_buf, start+4); + mdb_debug(MDB_DEBUG_OLE,"Reading LVAL page %06x", pg_row >> 8); + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return 0; + } + + mdb_debug(MDB_DEBUG_OLE,"row num %d start %d len %d", + pg_row & 0xff, row_start, len); + + if (dest) + memcpy(dest+cur, buf + row_start + 4, len - 4); + cur += len - 4; + + /* find next lval page */ + pg_row = mdb_get_int32(buf, row_start); + } while ((pg_row >> 8)); + return cur; + } else { + fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags); + return 0; + } +} +static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size) +{ + guint16 memo_len; + static char text[MDB_BIND_SIZE]; + guint16 memo_flags; + guint32 row_start, pg_row; + guint32 len; + char *buf; + + if (sizepg_buf, start, start + 12); +#endif + + /* The 16 bit integer at offset 0 is the length of the memo field. + * The 32 bit integer at offset 4 contains page and row information. + */ + memo_len = mdb_pg_get_int16(mdb, start); + memo_flags = mdb_pg_get_int16(mdb, start+2); + + if (memo_flags & 0x8000) { + /* inline memo field */ + strncpy(text, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD], + size - MDB_MEMO_OVERHEAD); + text[size - MDB_MEMO_OVERHEAD]='\0'; + return text; + } else if (memo_flags & 0x4000) { + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + if (mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); + buffer_dump(mdb->pg_buf, row_start, row_start + len); +#endif + if (IS_JET3(mdb)) { + strncpy(text, buf + row_start, len); + text[len]='\0'; + } else { + mdb_unicode2ascii(mdb, buf, row_start, len, text); + } + return text; + } else { /* if (memo_flags == 0x0000) { */ + pg_row = mdb_get_int32(mdb->pg_buf, start+4); +#if MDB_DEBUG + printf("Reading LVAL page %06x\n", pg_row >> 8); +#endif + text[0]='\0'; + do { + if (mdb_find_pg_row(mdb,pg_row,&buf,&row_start,&len)) { + return ""; + } +#if MDB_DEBUG + printf("row num %d start %d len %d\n", + pg_row & 0xff, row_start, len); +#endif + strncat(text, buf + row_start + 4, + strlen(text) + len - 4 > MDB_BIND_SIZE ? + MDB_BIND_SIZE - strlen(text) : len - 4); + + /* find next lval page */ + pg_row = mdb_get_int32(mdb->pg_buf, row_start); + } while ((pg_row >> 8)); + return text; +/* + } else { + fprintf(stderr,"Unhandled memo field flags = %04x\n", memo_flags); + return ""; +*/ + } +} +static char * +mdb_num_to_string(MdbHandle *mdb, int start, int datatype, int prec, int scale) +{ + char *text; + gint32 l; + + memcpy(&l, mdb->pg_buf+start+13, 4); + + text = (char *) g_malloc(prec+2); + sprintf(text, "%0*" G_GINT32_FORMAT, prec, GINT32_FROM_LE(l)); + if (scale) { + memmove(text+prec-scale, text+prec-scale+1, scale+1); + text[prec-scale] = '.'; + } + return text; +} + +static int trim_trailing_zeros(char * buff, int n) +{ + char * p = buff + n - 1; + + while (p >= buff && *p == '0') + *p-- = '\0'; + + if (*p == '.') + *p = '\0'; + + return 0; +} + +char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size) +{ + /* FIX ME -- not thread safe */ + static char text[MDB_BIND_SIZE]; + time_t t; + int n; + float tf; + double td; + + switch (datatype) { + case MDB_BOOL: + /* shouldn't happen. bools are handled specially + ** by mdb_xfer_bound_bool() */ + break; + case MDB_BYTE: + sprintf(text,"%d",mdb_get_byte(buf, start)); + return text; + break; + case MDB_INT: + sprintf(text,"%ld",(long)mdb_get_int16(buf, start)); + return text; + break; + case MDB_LONGINT: + sprintf(text,"%ld",mdb_get_int32(buf, start)); + return text; + break; + case MDB_FLOAT: + tf = mdb_get_single(mdb->pg_buf, start); + n = sprintf(text,"%.*f",FLT_DIG - (int)ceil(log10(tf)), tf); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_DOUBLE: + td = mdb_get_double(mdb->pg_buf, start); + n = sprintf(text,"%.*f",DBL_DIG - (int)ceil(log10(td)), td); + trim_trailing_zeros(text, n); + return text; + break; + case MDB_TEXT: + if (size<0) { + return ""; + } + if (IS_JET4(mdb)) { +/* + int i; + for (i=0;ipg_buf[start+i], mdb->pg_buf[start+i]); + } + fprintf(stdout, "\n"); +*/ + mdb_unicode2ascii(mdb, mdb->pg_buf, start, size, text); + } else { + strncpy(text, &buf[start], size); + text[size]='\0'; + } + return text; + break; + case MDB_SDATETIME: + td = mdb_get_double(mdb->pg_buf, start); + if (td > 1) { + t = (long int)((td - 25569.0) * 86400.0); + } else { + t = (long int)(td * 86400.0); + } + strftime(text, MDB_BIND_SIZE, date_fmt, (struct tm*)gmtime(&t)); + return text; + + break; + case MDB_MEMO: + return mdb_memo_to_string(mdb, start, size); + break; + case MDB_MONEY: + mdb_money_to_string(mdb, start, text); + return text; + case MDB_NUMERIC: + break; + default: + return ""; + break; + } + return NULL; +} +int mdb_col_disp_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return 4; + break; + case MDB_INT: + return 6; + break; + case MDB_LONGINT: + return 11; + break; + case MDB_FLOAT: + return 10; + break; + case MDB_DOUBLE: + return 10; + break; + case MDB_TEXT: + return col->col_size; + break; + case MDB_SDATETIME: + return 20; + break; + case MDB_MEMO: + return 255; + break; + case MDB_MONEY: + return 21; + break; + } + return 0; +} +int mdb_col_fixed_size(MdbColumn *col) +{ + switch (col->col_type) { + case MDB_BOOL: + return 1; + break; + case MDB_BYTE: + return -1; + break; + case MDB_INT: + return 2; + break; + case MDB_LONGINT: + return 4; + break; + case MDB_FLOAT: + return 4; + break; + case MDB_DOUBLE: + return 8; + break; + case MDB_TEXT: + return -1; + break; + case MDB_SDATETIME: + return 4; + break; + case MDB_MEMO: + return -1; + break; + case MDB_MONEY: + return 8; + break; + } + return 0; +} diff --git a/navit/src/data/poi_geodownload/libmdb/dump.c b/navit/src/data/poi_geodownload/libmdb/dump.c new file mode 100644 index 0000000..7ee17f9 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/dump.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void buffer_dump(const unsigned char* buf, int start, int end) +{ + char asc[20]; + int j, k; + + memset(asc, 0, sizeof(asc)); + k = 0; + for (j=start; j<=end; j++) { + if (k == 0) { + fprintf(stdout, "%04x ", j); + } + fprintf(stdout, "%02x ", buf[j]); + asc[k] = isprint(buf[j]) ? buf[j] : '.'; + k++; + if (k == 8) { + fprintf(stdout, " "); + } + if (k == 16) { + fprintf(stdout, " %s\n", asc); + memset(asc, 0, sizeof(asc)); + k = 0; + } + } + for (j=k; j<16; j++) { + fprintf(stdout, " "); + } + if (k < 8) { + fprintf(stdout, " "); + } + fprintf(stdout, " %s\n", asc); +} diff --git a/navit/src/data/poi_geodownload/libmdb/file.c b/navit/src/data/poi_geodownload/libmdb/file.c new file mode 100644 index 0000000..941830c --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/file.c @@ -0,0 +1,376 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; +*/ +MdbFormatConstants MdbJet4Constants = { + 4096, 0x0c, 16, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59, 7, 21, 9 +}; +MdbFormatConstants MdbJet3Constants = { + 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39, 3, 14, 5 /* not sure on 5, need to check */ +}; + +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg); + +/** + * mdb_find_file: + * @filename: path to MDB (database) file + * + * Finds and returns the absolute path to an MDB file. Function will first try + * to fstat file as passed, then search through the $MDBPATH if not found. + * + * Return value: gchar pointer to absolute path. Caller is responsible for + * freeing. + **/ + +static gchar *mdb_find_file(char *file_name) +{ + struct stat status; + gchar *mdbpath, **dir, *tmpfname; + unsigned int i = 0; + + /* try the provided file name first */ + if (!stat(file_name, &status)) { + return g_strdup(file_name); + } + + /* Now pull apart $MDBPATH and try those */ + mdbpath = (gchar *) getenv("MDBPATH"); + /* no path, can't find file */ + if (!mdbpath || !strlen(mdbpath)) return NULL; + + dir = g_strsplit(mdbpath, ":", 0); + while (dir[i]) { + if (!strlen(dir[i])) continue; + tmpfname = g_strconcat(dir[i++], "/", file_name, NULL); + if (!stat(tmpfname, &status)) { + g_strfreev(dir); + return tmpfname; + } + g_free(tmpfname); + } + g_strfreev(dir); + return NULL; +} +/** + * mdb_open: + * @filename: path to MDB (database) file + * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write + * + * Opens an MDB file and returns an MdbHandle to it. MDB File may be relative + * to the current directory, a full path to the file, or relative to a + * component of $MDBPATH. + * + * Return value: pointer to MdbHandle structure. + **/ +MdbHandle *mdb_open(char *filename, MdbFileFlags flags) +{ + MdbHandle *mdb; + + mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle)); + mdb_set_default_backend(mdb, "access"); + /* need something to bootstrap with, reassign after page 0 is read */ + mdb->fmt = &MdbJet3Constants; + mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile)); + mdb->f->refs = 1; + mdb->f->fd = -1; + mdb->f->filename = (char *) mdb_find_file(filename); + if (!mdb->f->filename) { + fprintf(stderr, "Can't alloc filename\n"); + mdb_close(mdb); + return NULL; + } + if (flags & MDB_WRITABLE) { + mdb->f->writable = TRUE; + mdb->f->fd = open(mdb->f->filename,O_RDWR); + } else { + mdb->f->fd = open(mdb->f->filename,O_RDONLY); + } + + if (mdb->f->fd==-1) { + fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); + mdb_close(mdb); + return NULL; + } + if (!mdb_read_pg(mdb, 0)) { + fprintf(stderr,"Couldn't read first page.\n"); + mdb_close(mdb); + return NULL; + } + if (mdb->pg_buf[0] != 0) { + mdb_close(mdb); + return NULL; + } + mdb->f->jet_version = mdb_pg_get_int32(mdb, 0x14); + if (IS_JET4(mdb)) { + mdb->fmt = &MdbJet4Constants; + } else if (IS_JET3(mdb)) { + mdb->fmt = &MdbJet3Constants; + } else { + fprintf(stderr,"Unknown Jet version.\n"); + mdb_close(mdb); + return NULL; + } + + return mdb; +} + +/** + * mdb_close: + * @mdb: Handle to open MDB database file + * + * Dereferences MDB file, closes if reference count is 0, and destroys handle. + * + **/ +void +mdb_close(MdbHandle *mdb) +{ + if (!mdb) return; + mdb_free_catalog(mdb); + g_free(mdb->stats); + g_free(mdb->backend_name); + + if (mdb->f) { + if (mdb->f->refs > 1) { + mdb->f->refs--; + } else { + if (mdb->f->fd != -1) close(mdb->f->fd); + g_free(mdb->f->filename); + g_free(mdb->f); + } + } + + g_free(mdb); +} +/** + * mdb_clone_handle: + * @mdb: Handle to open MDB database file + * + * Clones an existing database handle. Cloned handle shares the file descriptor + * but has its own page buffer, page position, and similar internal variables. + * + * Return value: new handle to the database. + */ +MdbHandle *mdb_clone_handle(MdbHandle *mdb) +{ + MdbHandle *newmdb; + MdbCatalogEntry *entry, *data; + unsigned int i; + + newmdb = (MdbHandle *) g_memdup(mdb, sizeof(MdbHandle)); + newmdb->stats = NULL; + newmdb->catalog = g_ptr_array_new(); + for (i=0;inum_catalog;i++) { + entry = g_ptr_array_index(mdb->catalog,i); + data = g_memdup(entry,sizeof(MdbCatalogEntry)); + g_ptr_array_add(newmdb->catalog, data); + } + mdb->backend_name = NULL; + if (mdb->f) { + mdb->f->refs++; + } + return newmdb; +} + +/* +** mdb_read a wrapper for read that bails if anything is wrong +*/ +ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + if (pg && mdb->cur_pg == pg) return mdb->fmt->pg_size; + + len = _mdb_read_pg(mdb, mdb->pg_buf, pg); + //fprintf(stderr, "read page %d type %02x\n", pg, mdb->pg_buf[0]); + mdb->cur_pg = pg; + /* kan - reset the cur_pos on a new page read */ + mdb->cur_pos = 0; /* kan */ + return len; +} +ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + + len = _mdb_read_pg(mdb, mdb->alt_pg_buf, pg); + return len; +} +static ssize_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + if (status.st_size < offset) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + if (mdb->stats && mdb->stats->collect) + mdb->stats->pg_reads++; + + lseek(mdb->f->fd, offset, SEEK_SET); + len = read(mdb->f->fd,pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("read"); + return 0; + } + else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->fmt->pg_size); */ + return 0; + } + return len; +} +void mdb_swap_pgbuf(MdbHandle *mdb) +{ +char tmpbuf[MDB_PGSIZE]; + + memcpy(tmpbuf,mdb->pg_buf, MDB_PGSIZE); + memcpy(mdb->pg_buf,mdb->alt_pg_buf, MDB_PGSIZE); + memcpy(mdb->alt_pg_buf,tmpbuf,MDB_PGSIZE); +} + + +/* really stupid, just here for consistancy */ +unsigned char mdb_get_byte(unsigned char *buf, int offset) +{ + return buf[offset]; +} +unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+1 > mdb->fmt->pg_size) return -1; + mdb->cur_pos++; + return mdb->pg_buf[offset]; +} + +int mdb_get_int16(unsigned char *buf, int offset) +{ + return buf[offset+1]*256+buf[offset]; +} +int mdb_pg_get_int16(MdbHandle *mdb, int offset) +{ + if (offset < 0 || offset+2 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=2; + return mdb_get_int16(mdb->pg_buf, offset); +} + +gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset) +{ + gint32 l = 0; + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + memcpy((char *)&l+1, &(mdb->pg_buf[offset]), 3); +#if 0 + printf("l=0x%08x 0x%08x\n",l,GINT32_FROM_BE(l)); +#endif + return GINT32_FROM_BE(l); +} +gint32 mdb_get_int24(unsigned char *buf, int offset) +{ + gint32 l = 0; + memcpy(&l, &buf[offset], 3); + return GINT32_FROM_LE(l); +} +gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=3; + return mdb_get_int24(mdb->pg_buf, offset); +} + +long mdb_get_int32(unsigned char *buf, int offset) +{ + guint32 l; + memcpy(&l, &buf[offset], 4); + return (long)GINT32_FROM_LE(l); +} +long mdb_pg_get_int32(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_int32(mdb->pg_buf, offset); +} + +float mdb_get_single(unsigned char *buf, int offset) +{ + union {guint32 g; float f;} f; + memcpy(&f, &buf[offset], 4); + f.g = GUINT32_FROM_LE(f.g); + return f.f; +} +float mdb_pg_get_single(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=4; + return mdb_get_single(mdb->pg_buf, offset); +} + +double mdb_get_double(unsigned char *buf, int offset) +{ + union {guint64 g; double d;} d; + memcpy(&d, &buf[offset], 8); + d.g = GUINT64_FROM_LE(d.g); + return d.d; +} +double mdb_pg_get_double(MdbHandle *mdb, int offset) +{ + if (offset <0 || offset+8 > mdb->fmt->pg_size) return -1; + mdb->cur_pos+=8; + return mdb_get_double(mdb->pg_buf, offset); +} + + +int +mdb_set_pos(MdbHandle *mdb, int pos) +{ + if (pos<0 || pos >= mdb->fmt->pg_size) return 0; + + mdb->cur_pos=pos; + return pos; +} +int mdb_get_pos(MdbHandle *mdb) +{ + return mdb->cur_pos; +} diff --git a/navit/src/data/poi_geodownload/libmdb/iconv.c b/navit/src/data/poi_geodownload/libmdb/iconv.c new file mode 100644 index 0000000..9f41afe --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/iconv.c @@ -0,0 +1,63 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +int +mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest) +{ + unsigned int i; + + if (buf[offset]==0xff && buf[offset+1]==0xfe) { + strncpy(dest, &buf[offset+2], len-2); + dest[len-2]='\0'; + } else { + /* convert unicode to ascii, rather sloppily */ + for (i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ICONV +#include +#endif + +#define MDB_DEBUG 0 + +#define MDB_PGSIZE 4096 +#define MDB_MAX_OBJ_NAME 256 +#define MDB_MAX_COLS 256 +#define MDB_MAX_IDX_COLS 10 +#define MDB_CATALOG_PG 18 +#define MDB_MEMO_OVERHEAD 12 +#define MDB_BIND_SIZE 16384 + +enum { + MDB_PAGE_DB = 0, + MDB_PAGE_DATA, + MDB_PAGE_TABLE, + MDB_PAGE_INDEX, + MDB_PAGE_LEAF, + MDB_PAGE_MAP +}; +enum { + MDB_VER_JET3 = 0, + MDB_VER_JET4 = 1 +}; +enum { + MDB_FORM = 0, + MDB_TABLE, + MDB_MACRO, + MDB_SYSTEM_TABLE, + MDB_REPORT, + MDB_QUERY, + MDB_LINKED_TABLE, + MDB_MODULE, + MDB_RELATIONSHIP, + MDB_UNKNOWN_09, + MDB_UNKNOWN_0A, + MDB_DATABASE_PROPERTY, + MDB_ANY = -1 +}; +enum { + MDB_BOOL = 0x01, + MDB_BYTE = 0x02, + MDB_INT = 0x03, + MDB_LONGINT = 0x04, + MDB_MONEY = 0x05, + MDB_FLOAT = 0x06, + MDB_DOUBLE = 0x07, + MDB_SDATETIME = 0x08, + MDB_TEXT = 0x0a, + MDB_OLE = 0x0b, + MDB_MEMO = 0x0c, + MDB_REPID = 0x0f, + MDB_NUMERIC = 0x10 +}; + +/* SARG operators */ +enum { + MDB_OR = 1, + MDB_AND, + MDB_NOT, + MDB_EQUAL, + MDB_GT, + MDB_LT, + MDB_GTEQ, + MDB_LTEQ, + MDB_LIKE, + MDB_ISNULL, + MDB_NOTNULL +}; + +typedef enum { + MDB_TABLE_SCAN, + MDB_LEAF_SCAN, + MDB_INDEX_SCAN +} MdbStrategy; + +typedef enum { + MDB_NOFLAGS = 0x00, + MDB_WRITABLE = 0x01 +} MdbFileFlags; + +enum { + MDB_DEBUG_LIKE = 0x0001, + MDB_DEBUG_WRITE = 0x0002, + MDB_DEBUG_USAGE = 0x0004, + MDB_DEBUG_OLE = 0x0008, + MDB_DEBUG_ROW = 0x0010, + MDB_USE_INDEX = 0x0020 +}; + +#define mdb_is_logical_op(x) (x == MDB_OR || \ + x == MDB_AND || \ + x == MDB_NOT ) + +#define mdb_is_relational_op(x) (x == MDB_EQUAL || \ + x == MDB_GT || \ + x == MDB_LT || \ + x == MDB_GTEQ || \ + x == MDB_LTEQ || \ + x == MDB_LIKE || \ + x == MDB_ISNULL || \ + x == MDB_NOTNULL ) + +enum { + MDB_ASC, + MDB_DESC +}; + +enum { + MDB_IDX_UNIQUE = 0x01, + MDB_IDX_IGNORENULLS = 0x02, + MDB_IDX_REQUIRED = 0x08 +}; + +#define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4) +#define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) + +/* hash to store registered backends */ +/* extern GHashTable *mdb_backends; */ + +/* forward declarations */ +typedef struct mdbindex MdbIndex; +typedef struct mdbsargtree MdbSargNode; + +typedef struct { + char *name; + unsigned char needs_length; /* or precision */ + unsigned char needs_scale; + unsigned char needs_quotes; +} MdbBackendType; + +typedef struct { + MdbBackendType *types_table; +} MdbBackend; + +typedef struct { + gboolean collect; + unsigned long pg_reads; +} MdbStatistics; + +typedef struct { + int fd; + gboolean writable; + char *filename; + guint32 jet_version; + guint32 db_key; + char db_passwd[14]; + MdbBackend *default_backend; + char *backend_name; + MdbStatistics *stats; + /* free map */ + int map_sz; + unsigned char *free_map; + /* reference count */ + int refs; +} MdbFile; + +/* offset to row count on data pages...version dependant */ +typedef struct { + int pg_size; + guint16 row_count_offset; + guint16 tab_num_rows_offset; + guint16 tab_num_cols_offset; + guint16 tab_num_idxs_offset; + guint16 tab_num_ridxs_offset; + guint16 tab_usage_map_offset; + guint16 tab_first_dpg_offset; + guint16 tab_cols_start_offset; + guint16 tab_ridx_entry_size; + guint16 col_fixed_offset; + guint16 col_size_offset; + guint16 col_num_offset; + guint16 tab_col_entry_size; + guint16 tab_free_map_offset; + guint16 tab_col_offset_var; + guint16 tab_col_offset_fixed; + guint16 tab_row_col_num_offset; +} MdbFormatConstants; + +typedef struct { + MdbFile *f; + guint32 cur_pg; + guint16 row_num; + unsigned int cur_pos; + unsigned char pg_buf[MDB_PGSIZE]; + unsigned char alt_pg_buf[MDB_PGSIZE]; + unsigned int num_catalog; + GPtrArray *catalog; + MdbBackend *default_backend; + char *backend_name; + MdbFormatConstants *fmt; + MdbStatistics *stats; +#ifdef HAVE_ICONV + iconv_t iconv_out; +#endif +} MdbHandle; + +typedef struct { + MdbHandle *mdb; + char object_name[MDB_MAX_OBJ_NAME+1]; + int object_type; + unsigned long table_pg; /* misnomer since object may not be a table */ + unsigned long kkd_pg; + unsigned int kkd_rowid; + int num_props; + GArray *props; + GArray *columns; + int flags; +} MdbCatalogEntry; + +typedef struct { + gchar *name; + GHashTable *hash; +} MdbProperties; + +typedef union { + int i; + double d; + char s[256]; +} MdbAny; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; + int col_type; + int col_size; + void *bind_ptr; + int *len_ptr; + GHashTable *properties; + unsigned int num_sargs; + GPtrArray *sargs; + GPtrArray *idx_sarg_cache; + unsigned char is_fixed; + int query_order; + /* col_num is the current column order, + * does not include deletes */ + int col_num; + int cur_value_start; + int cur_value_len; + /* MEMO/OLE readers */ + guint32 cur_blob_pg; + int cur_blob_row; + int chunk_size; + /* numerics only */ + int col_prec; + int col_scale; + MdbProperties *props; + /* info needed for handling deleted/added columns */ + int fixed_offset; + int var_col_num; + /* row_col_num is the row column number order, + * including deleted columns */ + int row_col_num; +} MdbColumn; + +struct mdbsargtree { + int op; + MdbColumn *col; + MdbAny value; + void *parent; + MdbSargNode *left; + MdbSargNode *right; +}; + +typedef struct { + guint32 pg; + int start_pos; + int offset; + int len; + guint16 idx_starts[2000]; + unsigned char cache_value[256]; +} MdbIndexPage; + +typedef int (*MdbSargTreeFunc)(MdbSargNode *, gpointer *data); + +#define MDB_MAX_INDEX_DEPTH 10 + +typedef struct { + int cur_depth; + guint32 last_leaf_found; + int clean_up_mode; + MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; +} MdbIndexChain; + +typedef struct { + MdbCatalogEntry *entry; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned int num_cols; + GPtrArray *columns; + unsigned int num_rows; + int index_start; + unsigned int num_real_idxs; + unsigned int num_idxs; + GPtrArray *indices; + guint32 first_data_pg; + guint32 cur_pg_num; + guint32 cur_phys_pg; + unsigned int cur_row; + int noskip_del; /* don't skip deleted rows */ + /* object allocation map */ + guint32 map_base_pg; + unsigned int map_sz; + unsigned char *usage_map; + /* pages with free space left */ + guint32 freemap_base_pg; + unsigned int freemap_sz; + unsigned char *free_usage_map; + /* query planner */ + MdbSargNode *sarg_tree; + MdbStrategy strategy; + MdbIndex *scan_idx; + MdbHandle *mdbidx; + MdbIndexChain *chain; + MdbProperties *props; + unsigned int num_var_cols; /* to know if row has variable columns */ + /* temp table */ + unsigned int is_temp_table; + GPtrArray *temp_table_pages; +} MdbTableDef; + +struct mdbindex { + int index_num; + char name[MDB_MAX_OBJ_NAME+1]; + unsigned char index_type; + guint32 first_pg; + int num_rows; /* number rows in index */ + unsigned int num_keys; + short key_col_num[MDB_MAX_IDX_COLS]; + unsigned char key_col_order[MDB_MAX_IDX_COLS]; + unsigned char flags; + MdbTableDef *table; +}; + +typedef struct { + char name[MDB_MAX_OBJ_NAME+1]; +} MdbColumnProp; + +typedef struct { + void *value; + int siz; + int start; + unsigned char is_null; + unsigned char is_fixed; + int colnum; + int offset; +} MdbField; + +typedef struct { + int op; + MdbAny value; +} MdbSarg; + +/* mem.c */ +extern void mdb_init(); +extern void mdb_exit(); + +/* file.c */ +extern ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg); +extern ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg); +extern unsigned char mdb_get_byte(unsigned char *buf, int offset); +extern int mdb_get_int16(unsigned char *buf, int offset); +extern gint32 mdb_get_int24(unsigned char *buf, int offset); +extern long mdb_get_int32(unsigned char *buf, int offset); +extern float mdb_get_single(unsigned char *buf, int offset); +extern double mdb_get_double(unsigned char *buf, int offset); +extern unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset); +extern int mdb_pg_get_int16(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset); +extern long mdb_pg_get_int32(MdbHandle *mdb, int offset); +extern float mdb_pg_get_single(MdbHandle *mdb, int offset); +extern double mdb_pg_get_double(MdbHandle *mdb, int offset); +extern gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset); +extern MdbHandle *mdb_open(char *filename, MdbFileFlags flags); +extern void mdb_close(MdbHandle *mdb); +extern MdbHandle *mdb_clone_handle(MdbHandle *mdb); +extern void mdb_swap_pgbuf(MdbHandle *mdb); +extern long _mdb_get_int32(unsigned char *buf, int offset); + +/* catalog.c */ +extern void mdb_free_catalog(MdbHandle *mdb); +extern GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type); +extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type); +extern char *mdb_get_objtype_string(int obj_type); + +/* table.c */ +extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry); +extern void mdb_free_tabledef(MdbTableDef *table); +extern MdbTableDef *mdb_read_table(MdbCatalogEntry *entry); +extern MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type); +extern void mdb_append_column(GPtrArray *columns, MdbColumn *in_col); +extern void mdb_free_columns(GPtrArray *columns); +extern GPtrArray *mdb_read_columns(MdbTableDef *table); +extern void mdb_table_dump(MdbCatalogEntry *entry); +extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos); +extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur_pos); +extern int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset); +extern guint16 read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len); +extern int mdb_is_user_table(MdbCatalogEntry *entry); +extern int mdb_is_system_table(MdbCatalogEntry *entry); + +/* data.c */ +extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr); +extern void mdb_data_dump(MdbTableDef *table); +extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr); +extern int mdb_rewind_table(MdbTableDef *table); +extern int mdb_fetch_row(MdbTableDef *table); +extern int mdb_is_fixed_col(MdbColumn *col); +extern char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size); +extern int mdb_find_pg_row(MdbHandle *mdb, int pg_row, char **buf, int *off, int *len); +extern int mdb_find_end_of_row(MdbHandle *mdb, int row); +extern int mdb_col_fixed_size(MdbColumn *col); +extern int mdb_col_disp_size(MdbColumn *col); +extern void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr); +extern int mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr); +extern int mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size); +extern void mdb_set_date_fmt(const char *); +extern int mdb_read_row(MdbTableDef *table, unsigned int row); + +/* dump.c */ +extern void buffer_dump(const unsigned char* buf, int start, int end); + +/* backend.c */ +extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); +extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); +extern void mdb_init_backends(); +extern void mdb_register_backend(MdbBackendType *backend, char *backend_name); +extern void mdb_remove_backends(); +extern int mdb_set_default_backend(MdbHandle *mdb, char *backend_name); +extern char *mdb_get_relationships(MdbHandle *mdb); + +/* sargs.c */ +extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields); +extern int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field); +extern void mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data); +extern int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data); +extern int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg); +extern int mdb_test_string(MdbSargNode *node, char *s); +extern int mdb_test_int(MdbSargNode *node, gint32 i); +extern int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg); + + + +/* index.c */ +extern GPtrArray *mdb_read_indices(MdbTableDef *table); +extern void mdb_index_dump(MdbTableDef *table, MdbIndex *idx); +extern void mdb_index_scan_free(MdbTableDef *table); +extern int mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg); +extern int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row); +extern void mdb_index_hash_text(guchar *text, guchar *hash); +extern void mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table); +extern int mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row); +extern void mdb_index_swap_n(unsigned char *src, int sz, unsigned char *dest); +extern void mdb_free_indices(GPtrArray *indices); +void mdb_index_page_reset(MdbIndexPage *ipg); +extern MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern MdbIndexPage *mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +extern void mdb_index_page_init(MdbIndexPage *ipg); + + +/* stats.c */ +extern void mdb_stats_on(MdbHandle *mdb); +extern void mdb_stats_off(MdbHandle *mdb); +extern void mdb_dump_stats(MdbHandle *mdb); + +/* like.c */ +extern int mdb_like_cmp(char *s, char *r); + +/* write.c */ +extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields); +extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size); +extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum); +extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields); +extern int mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size); +extern int mdb_pg_get_freespace(MdbHandle *mdb); +extern int mdb_update_row(MdbTableDef *table); +extern unsigned char *mdb_new_data_pg(MdbCatalogEntry *entry); + +/* map.c */ +extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size); +guint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg); + +/* props.c */ +extern GPtrArray *mdb_read_props_list(gchar *kkd, int len); +extern void mdb_free_props(MdbProperties *props); +extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len); + +/* worktable.c */ +extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name); +extern void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col); +extern void mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed); +extern void mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int column); +extern void mdb_temp_columns_end(MdbTableDef *table); + +/* options.c */ +extern int mdb_get_option(unsigned long optnum); +extern void mdb_debug(int klass, char *fmt, ...); + +/* iconv.c */ +extern int mdb_unicode2ascii(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); +extern int mdb_ascii2unicode(MdbHandle *mdb, unsigned char *buf, int offset, unsigned int len, char *dest); + +#endif /* _mdbtools_h_ */ diff --git a/navit/src/data/poi_geodownload/libmdb/index.c b/navit/src/data/poi_geodownload/libmdb/index.c new file mode 100644 index 0000000..e840536 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/index.c @@ -0,0 +1,905 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000-2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +MdbIndexPage *mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain); +MdbIndexPage *mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg); + +char idx_to_text[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0-7 0x00-0x07 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8-15 0x09-0x0f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 16-23 0x10-0x17 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24-31 0x19-0x1f */ +' ', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 32-39 0x20-0x27 */ +0x00, 0x00, 0x00, 0x00, 0x00, ' ', ' ', 0x00, /* 40-47 0x29-0x2f */ +'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', /* 48-55 0x30-0x37 */ +'^', '_', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 56-63 0x39-0x3f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 64-71 0x40-0x47 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 72-79 0x49-0x4f H */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 80-87 0x50-0x57 P */ +'|', '}', '~', '5', '6', '7', '8', '9', /* 88-95 0x59-0x5f */ +0x00, '`', 'a', 'b', 'd', 'f', 'g', 'h', /* 96-103 0x60-0x67 */ +'i', 'j', 'k', 'l', 'm', 'o', 'p', 'r', /* 014-111 0x69-0x6f h */ +'s', 't', 'u', 'v', 'w', 'x', 'z', '{', /* 112-119 0x70-0x77 p */ +'|', '}', '~', 0x00, 0x00, 0x00, 0x00, 0x00, /* 120-127 0x78-0x7f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 128-135 0x80-0x87 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */ +0x00, 0x00, 0x00, 0x00, 0x00, '`', 0x00, 0x00, /* 0xc0-0xc7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */ +0x00, '`', 0x00, '`', '`', '`', 0x00, 0x00, /* 0xe0-0xe7 */ +'f', 'f', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */ +0x00, 0x00, 0x00, 'r', 0x00, 0x00, 'r', 0x00, /* 0xf0-0xf7 */ +0x81, 0x00, 0x00, 0x00, 'x', 0x00, 0x00, 0x00, /* 0xf8-0xff */ +}; + + +GPtrArray * +mdb_read_indices(MdbTableDef *table) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbIndex *pidx; + unsigned int i, j; + int idx_num, key_num, col_num; + int cur_pos, name_sz, idx2_sz, type_offset; + int index_start_pg = mdb->cur_pg; + gchar *tmpbuf; + + table->indices = g_ptr_array_new(); + + if (IS_JET4(mdb)) { + cur_pos = table->index_start + 52 * table->num_real_idxs; + idx2_sz = 28; + type_offset = 23; + } else { + cur_pos = table->index_start + 39 * table->num_real_idxs; + idx2_sz = 20; + type_offset = 19; + } + + tmpbuf = (gchar *) g_malloc(idx2_sz); + for (i=0;inum_idxs;i++) { + read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); + cur_pos += idx2_sz; + pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex)); + pidx->table = table; + pidx->index_num = mdb_get_int16(tmpbuf, 4); + pidx->index_type = tmpbuf[type_offset]; + g_ptr_array_add(table->indices, pidx); + } + g_free(tmpbuf); + + for (i=0;inum_idxs;i++) { + pidx = g_ptr_array_index (table->indices, i); + if (IS_JET4(mdb)) { + name_sz=read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmpbuf = g_malloc(name_sz); + read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); + cur_pos += name_sz; + mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); + g_free(tmpbuf); + } else { + read_pg_if(mdb, &cur_pos, 0); + name_sz=mdb->pg_buf[cur_pos++]; + read_pg_if_n(mdb, pidx->name, &cur_pos, name_sz); + cur_pos += name_sz; + pidx->name[name_sz]='\0'; + } + //fprintf(stderr, "index name %s\n", pidx->name); + } + + mdb_read_alt_pg(mdb, entry->table_pg); + mdb_read_pg(mdb, index_start_pg); + cur_pos = table->index_start; + idx_num=0; + for (i=0;inum_real_idxs;i++) { + if (IS_JET4(mdb)) cur_pos += 4; + do { + pidx = g_ptr_array_index (table->indices, idx_num++); + } while (pidx && pidx->index_type==2); + + /* if there are more real indexes than index entries left after + removing type 2's decrement real indexes and continue. Happens + on Northwind Orders table. + */ + if (!pidx) { + table->num_real_idxs--; + continue; + } + + pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, + fmt->tab_cols_start_offset + + (i*fmt->tab_ridx_entry_size)); + + key_num=0; + for (j=0;jkey_col_num[key_num] = col_num + 1; + pidx->key_col_order[key_num] = + (mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC; + key_num++; + } + pidx->num_keys = key_num; + + cur_pos += 4; + pidx->first_pg = read_pg_if_32(mdb, &cur_pos); + cur_pos += 4; + read_pg_if(mdb, &cur_pos, 0); + pidx->flags = mdb->pg_buf[cur_pos++]; + if (IS_JET4(mdb)) cur_pos += 9; + } + return NULL; +} +void +mdb_index_hash_text(guchar *text, guchar *hash) +{ + unsigned int k; + + for (k=0;k 0; i--) { + dest[j++] = src[i]; + } +} +void +mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg) +{ + //guint32 cache_int; + unsigned char *c; + + switch (col->col_type) { + case MDB_TEXT: + mdb_index_hash_text(sarg->value.s, idx_sarg->value.s); + break; + + case MDB_LONGINT: + idx_sarg->value.i = GUINT32_SWAP_LE_BE(sarg->value.i); + //cache_int = sarg->value.i * -1; + c = (unsigned char *) &(idx_sarg->value.i); + c[0] |= 0x80; + //printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[2], c[3]); + break; + + case MDB_INT: + break; + + default: + break; + } +} +#if 0 +int +mdb_index_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSarg *sarg, int offset, int len) +{ +char tmpbuf[256]; +int lastchar; + + switch (col->col_type) { + case MDB_BYTE: + return mdb_test_int(sarg, mdb_pg_get_byte(mdb, offset)); + break; + case MDB_INT: + return mdb_test_int(sarg, mdb_pg_get_int16(mdb, offset)); + break; + case MDB_LONGINT: + return mdb_test_int(sarg, mdb_pg_get_int32(mdb, offset)); + break; + case MDB_TEXT: + strncpy(tmpbuf, &mdb->pg_buf[offset],255); + lastchar = len > 255 ? 255 : len; + tmpbuf[lastchar]='\0'; + return mdb_test_string(sarg, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +#endif +int +mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, unsigned char *buf, int len) +{ + unsigned int i, j; + MdbColumn *col; + MdbTableDef *table = idx->table; + MdbSarg *idx_sarg; + MdbSarg *sarg; + MdbField field; + MdbSargNode node; + //int c_offset = 0, + int c_len; + +#if 0 + fprintf(stderr,"mdb_index_test_sargs called on "); + for (i=0;ipg_buf[offset+i]); + fprintf(stderr,"\n"); +#endif + for (i=0;inum_keys;i++) { + //c_offset++; /* the per column null indicator/flags */ + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + /* + * This will go away eventually + */ + if (col->col_type==MDB_TEXT) { + //c_len = strlen(&mdb->pg_buf[offset + c_offset]); + c_len = strlen(buf); + } else { + c_len = col->col_size; + //fprintf(stderr,"Only text types currently supported. How did we get here?\n"); + } + /* + * If we have no cached index values for this column, + * create them. + */ + if (col->num_sargs && !col->idx_sarg_cache) { + col->idx_sarg_cache = g_ptr_array_new(); + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->sargs, j); + idx_sarg = g_memdup(sarg,sizeof(MdbSarg)); + //printf("calling mdb_index_cache_sarg\n"); + mdb_index_cache_sarg(col, sarg, idx_sarg); + g_ptr_array_add(col->idx_sarg_cache, idx_sarg); + } + } + + for (j=0;jnum_sargs;j++) { + sarg = g_ptr_array_index (col->idx_sarg_cache, j); + /* XXX - kludge */ + node.op = sarg->op; + node.value = sarg->value; + //field.value = &mdb->pg_buf[offset + c_offset]; + field.value = buf; + field.siz = c_len; + field.is_null = FALSE; + if (!mdb_test_sarg(mdb, col, &node, &field)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + } + return 1; +} +/* + * pack the pages bitmap + */ +int +mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte = 0; + int elem = 0; + int len, start, i; + + start = ipg->idx_starts[elem++]; + + while (start) { + len = ipg->idx_starts[elem] - start; + fprintf(stdout, "len is %d\n", len); + for (i=0; i < len; i++) { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mdb->pg_buf[mask_pos++] = mask_byte; + mask_byte = 0; + } + /* upon reaching the len, set the bit */ + } + mask_byte = (1 << mask_bit) | mask_byte; + fprintf(stdout, "mask byte is %02x at %d\n", mask_byte, mask_pos); + start = ipg->idx_starts[elem++]; + } + /* flush the last byte if any */ + mdb->pg_buf[mask_pos++] = mask_byte; + /* remember to zero the rest of the bitmap */ + for (i = mask_pos; i < 0xf8; i++) { + mdb->pg_buf[mask_pos++] = 0; + } + return 0; +} +/* + * unpack the pages bitmap + */ +int +mdb_index_unpack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) +{ + int mask_bit = 0; + int mask_pos = 0x16; + int mask_byte; + int start = 0xf8; + int elem = 0; + int len = 0; + + ipg->idx_starts[elem++]=start; + +#if 0 + fprintf(stdout, "Unpacking index page %u\n", ipg->pg); +#endif + do { + len = 0; + do { + mask_bit++; + if (mask_bit==8) { + mask_bit=0; + mask_pos++; + } + mask_byte = mdb->pg_buf[mask_pos]; + len++; + } while (mask_pos <= 0xf8 && !((1 << mask_bit) & mask_byte)); + //fprintf(stdout, "%d %d %d %d\n", mask_pos, mask_bit, mask_byte, len); + + start += len; + if (mask_pos < 0xf8) ipg->idx_starts[elem++]=start; + + } while (mask_pos < 0xf8); + + /* if we zero the next element, so we don't pick up the last pages starts*/ + ipg->idx_starts[elem]=0; + + return elem; +} +/* + * find the next entry on a page (either index or leaf). Uses state information + * stored in the MdbIndexPage across calls. + */ +int +mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg) +{ + if (!ipg->pg) return 0; + + /* if this page has not been unpacked to it */ + if (!ipg->idx_starts[0]){ + //fprintf(stdout, "Unpacking page %d\n", ipg->pg); + mdb_index_unpack_bitmap(mdb, ipg); + } + + + if (ipg->idx_starts[ipg->start_pos + 1]==0) return 0; + ipg->len = ipg->idx_starts[ipg->start_pos+1] - ipg->idx_starts[ipg->start_pos]; + ipg->start_pos++; + //fprintf(stdout, "Start pos %d\n", ipg->start_pos); + + return ipg->len; +} +void mdb_index_page_reset(MdbIndexPage *ipg) +{ + ipg->offset = 0xf8; /* start byte of the index entries */ + ipg->start_pos=0; + ipg->len = 0; + ipg->idx_starts[0]=0; +} +void mdb_index_page_init(MdbIndexPage *ipg) +{ + memset(ipg, 0, sizeof(MdbIndexPage)); + mdb_index_page_reset(ipg); +} +/* + * find the next leaf page if any given a chain. Assumes any exhausted leaf + * pages at the end of the chain have been peeled off before the call. + */ +MdbIndexPage * +mdb_find_next_leaf(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg, *newipg; + guint32 pg; + guint passed = 0; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * If we are at the first page deep and it's not an index page then + * we are simply done. (there is no page to find + */ + + if (mdb->pg_buf[0]==MDB_PAGE_LEAF) { + /* Indexes can have leaves at the end that don't appear + * in the upper tree, stash the last index found so + * we can follow it at the end. */ + chain->last_leaf_found = ipg->pg; + return ipg; + } + + /* + * apply sargs here, currently we don't + */ + do { + ipg->len = 0; + //printf("finding next on pg %lu\n", ipg->pg); + if (!mdb_index_find_next_on_page(mdb, ipg)) { + //printf("find_next_on_page returned 0\n"); + return 0; + } + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 3); + //printf("Looking at pg %lu at %lu %d\n", pg, ipg->offset, ipg->len); + ipg->offset += ipg->len; + + /* + * add to the chain and call this function + * recursively. + */ + newipg = mdb_chain_add_page(mdb, chain, pg); + newipg = mdb_find_next_leaf(mdb, idx, chain); + //printf("returning pg %lu\n",newipg->pg); + return newipg; + } while (!passed); + /* no more pages */ + return NULL; + +} +MdbIndexPage * +mdb_chain_add_page(MdbHandle *mdb, MdbIndexChain *chain, guint32 pg) +{ + MdbIndexPage *ipg; + + chain->cur_depth++; + if (chain->cur_depth > MDB_MAX_INDEX_DEPTH) { + fprintf(stderr,"Error! maximum index depth of %d exceeded. This is probably due to a programming bug, If you are confident that your indexes really are this deep, adjust MDB_MAX_INDEX_DEPTH in mdbtools.h and recompile.\n", MDB_MAX_INDEX_DEPTH); + exit(1); + } + ipg = &(chain->pages[chain->cur_depth - 1]); + mdb_index_page_init(ipg); + ipg->pg = pg; + + return ipg; +} +/* + * returns the bottom page of the IndexChain, if IndexChain is empty it + * initializes it by reading idx->first_pg (the root page) + */ +MdbIndexPage * +mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + /* + * if it's new use the root index page (idx->first_pg) + */ + if (!chain->cur_depth) { + ipg = &(chain->pages[0]); + mdb_index_page_init(ipg); + chain->cur_depth = 1; + ipg->pg = idx->first_pg; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + } else { + ipg = &(chain->pages[chain->cur_depth - 1]); + ipg->len = 0; + } + + mdb_read_pg(mdb, ipg->pg); + + return ipg; +} +/* + * unwind the stack and search for new leaf node + */ +MdbIndexPage * +mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + //printf("page %lu finished\n",ipg->pg); + if (chain->cur_depth==1) { + //printf("cur_depth == 1 we're out\n"); + return NULL; + } + /* + * unwind the stack until we find something or reach + * the top. + */ + ipg = NULL; + while (chain->cur_depth>1 && ipg==NULL) { + //printf("chain depth %d\n", chain->cur_depth); + chain->cur_depth--; + ipg = mdb_find_next_leaf(mdb, idx, chain); + if (ipg) mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) { + //printf("last leaf %lu\n", chain->last_leaf_found); + return NULL; + } + return ipg; +} +/* + * the main index function. + * caller provides an index chain which is the current traversal of index + * pages from the root page to the leaf. Initially passed as blank, + * mdb_index_find_next will store it's state information here. Each invocation + * then picks up where the last one left off, allowing us to scroll through + * the index one by one. + * + * Sargs are applied here but also need to be applied on the whole row b/c + * text columns may return false positives due to hashing and non-index + * columns with sarg values can't be tested here. + */ +int +mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row) +{ + MdbIndexPage *ipg; + int passed = 0; + int idx_sz; + int idx_start = 0; + MdbColumn *col; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + /* + * loop while the sargs don't match + */ + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + if (!chain->clean_up_mode) { + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) return 0; + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) + return 0; + } + } + *row = mdb->pg_buf[ipg->offset + ipg->len - 1]; +#if 0 + printf("page: "); + buffer_dump(mdb->pg_buf, ipg->offset+ipg->len-4, ipg->offset+ipg->len-2); +#endif + *pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); +#if 0 + printf("row = %d pg = %lu ipg->pg = %lu offset = %lu len = %d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len); +#endif + col=g_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1); + idx_sz = mdb_col_fixed_size(col); + /* handle compressed indexes, single key indexes only? */ + if (idx->num_keys==1 && idx_sz>0 && ipg->len - 4 < idx_sz) { +#if 0 + printf("short index found\n"); + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->offset], ipg->len); +#if 0 + buffer_dump(ipg->cache_value, 0, idx_sz); +#endif + } else { + idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz); + } + + //idx_start = ipg->offset + (ipg->len - 4 - idx_sz); + passed = mdb_index_test_sargs(mdb, idx, ipg->cache_value, idx_sz); + +// printf("passed=%d\n", passed); + + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); + ipg->offset += ipg->len; + + } while (!passed); + +#if 0 + fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->len); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + + return ipg->len; +} +/* + * XXX - FIX ME + * This function is grossly inefficient. It scans the entire index building + * an IndexChain to a specific row. We should be checking the index pages + * for matches against the indexed fields to find the proper leaf page, but + * getting it working first and then make it fast! + */ +int +mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row) +{ + MdbIndexPage *ipg; + int passed = 0; + guint32 datapg; + guint16 datarow; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + + do { + ipg->len = 0; + /* + * if no more rows on this leaf, try to find a new leaf + */ + if (!mdb_index_find_next_on_page(mdb, ipg)) { + /* back to top? We're done */ + if (chain->cur_depth==1) + return 0; + + /* + * unwind the stack until we find something or reach + * the top. + */ + while (chain->cur_depth>1) { + chain->cur_depth--; + if (!(ipg = mdb_find_next_leaf(mdb, idx, chain))) + return 0; + mdb_index_find_next_on_page(mdb, ipg); + } + if (chain->cur_depth==1) + return 0; + } + /* test row and pg */ + datarow = mdb->pg_buf[ipg->offset + ipg->len - 1]; + datapg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + + if (datapg == pg && datarow == row) { + passed = 1; + } + ipg->offset += ipg->len; + } while (!passed); + + /* index chain from root to leaf should now be in "chain" */ + return 1; +} + +void mdb_index_walk(MdbTableDef *table, MdbIndex *idx) +{ +MdbHandle *mdb = table->entry->mdb; +int cur_pos = 0; +unsigned char marker; +MdbColumn *col; +unsigned int i; + + if (idx->num_keys!=1) return; + + mdb_read_pg(mdb, idx->first_pg); + cur_pos = 0xf8; + + for (i=0;inum_keys;i++) { + marker = mdb->pg_buf[cur_pos++]; + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + //printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_col_fixed_size(col), col->col_size); + } +} +void +mdb_index_dump(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + + fprintf(stdout,"index number %d\n", idx->index_num); + fprintf(stdout,"index name %s\n", idx->name); + fprintf(stdout,"index first page %d\n", idx->first_pg); + fprintf(stdout,"index rows %d\n", idx->num_rows); + if (idx->index_type==1) fprintf(stdout,"index is a primary key\n"); + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + fprintf(stdout,"Column %s(%d) Sorted %s Unique: %s\n", + col->name, + idx->key_col_num[i], + idx->key_col_order[i]==MDB_ASC ? "ascending" : "descending", + idx->flags & MDB_IDX_UNIQUE ? "Yes" : "No" + ); + } + mdb_index_walk(table, idx); +} +/* + * compute_cost tries to assign a cost to a given index using the sargs + * available in this query. + * + * Indexes with no matching sargs are assigned 0 + * Unique indexes are preferred over non-uniques + * Operator preference is equal, like, isnull, others + */ +int mdb_index_compute_cost(MdbTableDef *table, MdbIndex *idx) +{ + unsigned int i; + MdbColumn *col; + MdbSarg *sarg = NULL; + int not_all_equal = 0; + + if (!idx->num_keys) return 0; + if (idx->num_keys > 1) { + for (i=0;inum_keys;i++) { + col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1); + if (col->sargs) sarg = g_ptr_array_index (col->sargs, 0); + if (!sarg || sarg->op != MDB_EQUAL) not_all_equal++; + } + } + + col=g_ptr_array_index(table->columns,idx->key_col_num[0]-1); + /* + * if this is the first key column and there are no sargs, + * then this index is useless. + */ + if (!col->num_sargs) return 0; + + sarg = g_ptr_array_index (col->sargs, 0); + + /* + * a like with a wild card first is useless as a sarg */ + if (sarg->op == MDB_LIKE && sarg->value.s[0]=='%') + return 0; + + /* + * this needs a lot of tweaking. + */ + if (idx->flags & MDB_IDX_UNIQUE) { + if (idx->num_keys == 1) { + //printf("op is %d\n", sarg->op); + switch (sarg->op) { + case MDB_EQUAL: + return 1; break; + case MDB_LIKE: + return 4; break; + case MDB_ISNULL: + return 12; break; + default: + return 8; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 2; + else return 1; + break; + case MDB_LIKE: + return 6; break; + case MDB_ISNULL: + return 12; break; + default: + return 9; break; + } + } + } else { + if (idx->num_keys == 1) { + switch (sarg->op) { + case MDB_EQUAL: + return 2; break; + case MDB_LIKE: + return 5; break; + case MDB_ISNULL: + return 12; break; + default: + return 10; break; + } + } else { + switch (sarg->op) { + case MDB_EQUAL: + if (not_all_equal) return 3; + else return 2; + break; + case MDB_LIKE: + return 7; break; + case MDB_ISNULL: + return 12; break; + default: + return 11; break; + } + } + } + return 0; +} +/* + * choose_index runs mdb_index_compute_cost for each available index and picks + * the best. + * + * Returns strategy to use (table scan, or index scan) + */ +MdbStrategy +mdb_choose_index(MdbTableDef *table, int *choice) +{ + unsigned int i; + MdbIndex *idx; + int cost = 0; + int least = 99; + + *choice = -1; + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + cost = mdb_index_compute_cost(table, idx); + //printf("cost for %s is %d\n", idx->name, cost); + if (cost && cost < least) { + least = cost; + *choice = i; + } + } + /* and the winner is: *choice */ + if (least==99) return MDB_TABLE_SCAN; + return MDB_INDEX_SCAN; +} +void +mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table) +{ + int i; + + if (mdb_get_option(MDB_USE_INDEX) && mdb_choose_index(table, &i) == MDB_INDEX_SCAN) { + table->strategy = MDB_INDEX_SCAN; + table->scan_idx = g_ptr_array_index (table->indices, i); + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + //printf("best index is %s\n",table->scan_idx->name); + } + //printf("TABLE SCAN? %d\n", table->strategy); +} +void +mdb_index_scan_free(MdbTableDef *table) +{ + if (table->chain) { + g_free(table->chain); + table->chain = NULL; + } + if (table->mdbidx) { + mdb_close(table->mdbidx); + table->mdbidx = NULL; + } +} + +void mdb_free_indices(GPtrArray *indices) +{ + unsigned int i; + + if (!indices) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(indices, i)); + g_ptr_array_free(indices, TRUE); +} diff --git a/navit/src/data/poi_geodownload/libmdb/kkd.c b/navit/src/data/poi_geodownload/libmdb/kkd.c new file mode 100644 index 0000000..ea72887 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/kkd.c @@ -0,0 +1,149 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +/* +** Note: This code is mostly garbage right now...just a test to parse out the +** KKD structures. +*/ + +GArray *mdb_get_column_props(MdbCatalogEntry *entry, int start) +{ +int pos, cnt=0; +int len, tmp, cplen; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; + + entry->props = g_array_new(FALSE,FALSE,sizeof(MdbColumnProp)); + len = mdb_pg_get_int16(mdb,start); + pos = start + 6; + while (pos < start+len) { + tmp = mdb_pg_get_int16(mdb,pos); /* length of string */ + pos += 2; + cplen = tmp > MDB_MAX_OBJ_NAME ? MDB_MAX_OBJ_NAME : tmp; + g_memmove(prop.name,&mdb->pg_buf[pos],cplen); + prop.name[cplen]='\0'; + pos += tmp; + g_array_append_val(entry->props, prop.name); + cnt++; + } + entry->num_props = cnt; + return entry->props; +} + +GHashTable *mdb_get_column_def(MdbCatalogEntry *entry, int start) +{ +GHashTable *hash = NULL; +MdbHandle *mdb = entry->mdb; +MdbColumnProp prop; +int tmp, pos, col_num, val_len, i; +int len, col_type; +unsigned char c; +int end; + + fprintf(stdout,"\n data\n"); + fprintf(stdout,"-------\n"); + len = mdb_pg_get_int16(mdb,start); + fprintf(stdout,"length = %3d\n",len); + pos = start + 6; + end = start + len; + while (pos < end) { + fprintf(stdout,"pos = %3d\n",pos); + start = pos; + tmp = mdb_pg_get_int16(mdb,pos); /* length of field */ + pos += 2; + col_type = mdb_pg_get_int16(mdb,pos); /* ??? */ + pos += 2; + col_num = 0; + if (col_type) { + col_num = mdb_pg_get_int16(mdb,pos); + pos += 2; + } + val_len = mdb_pg_get_int16(mdb,pos); + pos += 2; + fprintf(stdout,"length = %3d %04x %2d %2d ",tmp, col_type, col_num, val_len); + for (i=0;ipg_buf[pos+i]; + if (isprint(c)) + fprintf(stdout," %c",c); + else + fprintf(stdout," %02x",c); + + } + pos = start + tmp; + prop = g_array_index(entry->props,MdbColumnProp,col_num); + fprintf(stdout," Property %s",prop.name); + fprintf(stdout,"\n"); + } + return hash; +} +void mdb_kkd_dump(MdbCatalogEntry *entry) +{ +int rows; +int kkd_start, kkd_end; +int i, tmp, pos, row_type, datapos=0; +MdbColumnProp prop; +MdbHandle *mdb = entry->mdb; +int rowid = entry->kkd_rowid; + + + mdb_read_pg(mdb, entry->kkd_pg); + rows = mdb_pg_get_int16(mdb,8); + fprintf(stdout,"number of rows = %d\n",rows); + kkd_start = mdb_pg_get_int16(mdb,10+rowid*2); + fprintf(stdout,"kkd start = %d %04x\n",kkd_start,kkd_start); + kkd_end = mdb->fmt->pg_size; + for (i=0;ifmt->pg_size && + tmp > kkd_start && + tmp < kkd_end) { + kkd_end = tmp; + } + } + fprintf(stdout,"kkd end = %d %04x\n",kkd_end,kkd_end); + pos = kkd_start + 4; /* 4 = K K D \0 */ + while (pos < kkd_end) { + tmp = mdb_pg_get_int16(mdb,pos); + row_type = mdb_pg_get_int16(mdb,pos+4); + fprintf(stdout,"row size = %3d type = 0x%02x\n",tmp,row_type); + if (row_type==0x80) { + fprintf(stdout,"\nColumn Properties\n"); + fprintf(stdout,"-----------------\n"); + mdb_get_column_props(entry,pos); + for (i=0;inum_props;i++) { + prop = g_array_index(entry->props,MdbColumnProp,i); + fprintf(stdout,"%3d %s\n",i,prop.name); + } + } + if (row_type==0x01) datapos = pos; + pos += tmp; + } + + if (datapos) { + mdb_get_column_def(entry, datapos); + } +} + diff --git a/navit/src/data/poi_geodownload/libmdb/like.c b/navit/src/data/poi_geodownload/libmdb/like.c new file mode 100644 index 0000000..0a23d45 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/like.c @@ -0,0 +1,78 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_like_cmp + * @s: String to search within. + * @r: Search pattern. + * + * Tests the string @s to see if it matches the search pattern @r. In the + * search pattern, a percent sign indicates matching on any number of + * characters, and an underscore indicates matching any single character. + * + * Returns: 1 if the string matches, 0 if the string does not match. + */ +int mdb_like_cmp(char *s, char *r) +{ + unsigned int i; + int ret; + + mdb_debug(MDB_DEBUG_LIKE, "comparing %s and %s", s, r); + switch (r[0]) { + case '\0': + if (s[0]=='\0') { + return 1; + } else { + return 0; + } + case '_': + /* skip one character */ + return mdb_like_cmp(&s[1],&r[1]); + case '%': + /* skip any number of characters */ + /* the strlen(s)+1 is important so the next call can */ + /* if there are trailing characters */ + for(i=0;i= pgnum) ? start_pg-pgnum+1 : 0; + for (; ifmt->pg_size - 4) * 8 pages. + * + * map_ind gives us the starting usage_map entry + * offset gives us a page offset into the bitmap + */ + usage_bitlen = (mdb->fmt->pg_size - 4) * 8; + max_map_pgs = (map_sz - 1) / 4; + map_ind = (start_pg + 1) / usage_bitlen; + offset = (start_pg + 1) % usage_bitlen; + + for (; map_indfmt->pg_size) { + fprintf(stderr, "Oops! didn't get a full page at %d\n", map_pg); + exit(1); + } + + usage_bitmap = mdb->alt_pg_buf + 4; + for (i=offset; ientry; + MdbHandle *mdb = entry->mdb; + guint32 pgnum; + guint32 cur_pg = 0; + int free_space; + + do { + pgnum = mdb_map_find_next(mdb, + table->free_usage_map, + table->freemap_sz, cur_pg); + printf("looking at page %d\n", pgnum); + if (!pgnum) { + /* allocate new page */ + pgnum = mdb_alloc_page(table); + return pgnum; + } + cur_pg = pgnum; + + mdb_read_pg(mdb, pgnum); + free_space = mdb_pg_get_freespace(mdb); + + } while (free_space < row_size); + + printf("page %d has %d bytes left\n", pgnum, free_space); + + return pgnum; +} diff --git a/navit/src/data/poi_geodownload/libmdb/mem.c b/navit/src/data/poi_geodownload/libmdb/mem.c new file mode 100644 index 0000000..9c51832 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/mem.c @@ -0,0 +1,50 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_init: + * + * Initializes the LibMDB library. This function should be called exactly once + * by calling program and prior to any other function. + * + **/ +void mdb_init() +{ + mdb_init_backends(); +} + +/** + * mdb_exit: + * + * Cleans up the LibMDB library. This function should be called exactly once + * by the calling program prior to exiting (or prior to final use of LibMDB + * functions). + * + **/ +void mdb_exit() +{ + mdb_remove_backends(); +} diff --git a/navit/src/data/poi_geodownload/libmdb/money.c b/navit/src/data/poi_geodownload/libmdb/money.c new file mode 100644 index 0000000..7f2cf65 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/money.c @@ -0,0 +1,139 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 1998-1999 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define MAXPRECISION 20 +/* +** these routines are copied from the freetds project which does something +** very similiar +*/ + +static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier); +static int do_carry(unsigned char *product); +static char *array_to_string(unsigned char *array, int unsigned scale, char *s); + +/** + * mdb_money_to_string + * @mdb: Handle to open MDB database file + * @start: Offset of the field within the current page + * @s: String that will receieve the value + * + * Returns: the string that has received the value. + */ +char *mdb_money_to_string(MdbHandle *mdb, int start, char *s) +{ + int num_bytes = 8; + int i; + int neg=0; + unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION]; + unsigned char product[MAXPRECISION]; + unsigned char money[num_bytes]; + + memset(multiplier,0,MAXPRECISION); + memset(product,0,MAXPRECISION); + multiplier[0]=1; + memcpy(money, mdb->pg_buf + start, num_bytes); + + /* Perform two's complement for negative numbers */ + if (money[7] & 0x80) { + neg = 1; + for (i=0;i9) { + product[j+1]+=product[j]/10; + product[j]=product[j]%10; + } + } + if (product[j]>9) { + product[j]=product[j]%10; + } + return 0; +} +static char *array_to_string(unsigned char *array, unsigned int scale, char *s) +{ + unsigned int top, i, j=0; + + for (top=MAXPRECISION;(top>0) && (top-1>scale) && !array[top-1];top--); + + if (top == 0) { + s[j++] = '0'; + } else { + for (i=top; i>0; i--) { + if (j == top-scale) s[j++]='.'; + s[j++]=array[i-1]+'0'; + } + } + s[j]='\0'; + + return s; +} diff --git a/navit/src/data/poi_geodownload/libmdb/options.c b/navit/src/data/poi_geodownload/libmdb/options.c new file mode 100644 index 0000000..cdbbc66 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/options.c @@ -0,0 +1,86 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include + +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#define DEBUG 1 + +static unsigned long opts; +static int optset; + +static void load_options(); + +void +mdb_debug(int klass, char *fmt, ...) +{ +#ifdef DEBUG + va_list ap; + + if (!optset) load_options(); + if (klass & opts) { + va_start(ap, fmt); + vfprintf (stdout,fmt, ap); + va_end(ap); + fprintf(stdout,"\n"); + } +#endif +} + +static void +load_options() +{ + char *opt; + char *s; + + if (!optset && (s=getenv("MDBOPTS"))) { + opt = strtok(s, ":"); + do { + if (!strcmp(opt, "use_index")) opts |= MDB_USE_INDEX; + if (!strcmp(opt, "debug_like")) opts |= MDB_DEBUG_LIKE; + if (!strcmp(opt, "debug_write")) opts |= MDB_DEBUG_WRITE; + if (!strcmp(opt, "debug_usage")) opts |= MDB_DEBUG_USAGE; + if (!strcmp(opt, "debug_ole")) opts |= MDB_DEBUG_OLE; + if (!strcmp(opt, "debug_row")) opts |= MDB_DEBUG_ROW; + if (!strcmp(opt, "debug_all")) { + opts |= MDB_DEBUG_LIKE; + opts |= MDB_DEBUG_WRITE; + opts |= MDB_DEBUG_USAGE; + opts |= MDB_DEBUG_OLE; + opts |= MDB_DEBUG_ROW; + } + opt = strtok(NULL,":"); + } while (opt); + } + optset = 1; +} +int +mdb_get_option(unsigned long optnum) +{ + if (!optset) load_options(); + return ((opts & optnum) > 0); +} diff --git a/navit/src/data/poi_geodownload/libmdb/props.c b/navit/src/data/poi_geodownload/libmdb/props.c new file mode 100644 index 0000000..61db9f5 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/props.c @@ -0,0 +1,127 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +GPtrArray * +mdb_read_props_list(gchar *kkd, int len) +{ + guint32 record_len; + int pos = 0; + gchar *name; + GPtrArray *names = NULL; + int i = 0; + + names = g_ptr_array_new(); +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + pos += 2; +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos - 2, pos + record_len - 1); +#endif + name = g_malloc(record_len + 1); + strncpy(name, &kkd[pos], record_len); + name[record_len] = '\0'; + pos += record_len; + g_ptr_array_add(names, name); +#ifdef MDB_DEBUG + printf("new len = %d\n", names->len); +#endif + } + return names; +} +void +mdb_free_props(MdbProperties *props) +{ + if (!props) return; + + if (props->name) g_free(props->name); + g_free(props); +} +MdbProperties * +mdb_alloc_props() +{ + MdbProperties *props; + + props = g_malloc0(sizeof(MdbProperties)); + + return props; +} +MdbProperties * +mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len) +{ + guint32 record_len, name_len; + int pos = 0; + int elem, dtype, dsize; + gchar *name, *value; + MdbProperties *props; + int i = 0; + +#ifdef MDB_DEBUG + buffer_dump(kkd, 0, len - 1); +#endif + pos = 0; + + /* skip the name record */ + record_len = mdb_get_int16(kkd, pos); + pos += 4; + name_len = mdb_get_int16(kkd, pos); + pos += 2; + props = mdb_alloc_props(); + if (name_len) { + props->name = g_malloc(name_len + 1); + strncpy(props->name, &kkd[pos], name_len); + props->name[name_len]='\0'; + } + pos += name_len; + + props->hash = g_hash_table_new(g_str_hash, g_str_equal); + + while (pos < len) { + record_len = mdb_get_int16(kkd, pos); + elem = mdb_get_int16(kkd, pos + 4); + dtype = kkd[pos + 3]; + dsize = mdb_get_int16(kkd, pos + 6); + value = g_malloc(dsize + 1); + strncpy(value, &kkd[pos + 8], dsize); + value[dsize] = '\0'; + name = g_ptr_array_index(names,elem); +#ifdef MDB_DEBUG + printf("%02d ",i++); + buffer_dump(kkd, pos, pos + record_len - 1); + printf("elem %d dsize %d dtype %d\n", elem, dsize, dtype); +#endif + if (dtype == MDB_MEMO) dtype = MDB_TEXT; + if (dtype == MDB_BOOL) { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(kkd[pos + 8] ? "yes" : "no")); + } else { + g_hash_table_insert(props->hash, g_strdup(name), g_strdup(mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize))); + } + g_free(value); + pos += record_len; + } + return props; + +} diff --git a/navit/src/data/poi_geodownload/libmdb/sargs.c b/navit/src/data/poi_geodownload/libmdb/sargs.c new file mode 100644 index 0000000..b14aaa9 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/sargs.c @@ -0,0 +1,273 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * code for handling searchable arguments (sargs) used primary by the sql + * engine to support where clause handling. The sargs are configured in + * a tree with AND/OR operators connecting the child nodes. NOT operations + * have only one child on the left side. Logical operators (=,<,>,etc..) + * have no children. + * + * datatype support is a bit weak at this point. To add more types create + * a mdb_test_[type]() function and invoke it from mdb_test_sarg() + */ +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +void +mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data) +{ + if (func(node, data)) + return; + if (node->left) mdb_sql_walk_tree(node->left, func, data); + if (node->right) mdb_sql_walk_tree(node->right, func, data); +} +int +mdb_test_string(MdbSargNode *node, char *s) +{ +int rc; + + if (node->op == MDB_LIKE) { + return mdb_like_cmp(s,node->value.s); + } + rc = strncmp(node->value.s, s, 255); + switch (node->op) { + case MDB_EQUAL: + if (rc==0) return 1; + break; + case MDB_GT: + if (rc<0) return 1; + break; + case MDB_LT: + if (rc>0) return 1; + break; + case MDB_GTEQ: + if (rc<=0) return 1; + break; + case MDB_LTEQ: + if (rc>=0) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_string() for operator %d\n",node->op); + break; + } + return 0; +} +int mdb_test_int(MdbSargNode *node, gint32 i) +{ + switch (node->op) { + case MDB_EQUAL: + printf("comparing %x and %x %d\n", i, node->value.i, node->value.i == i); + if (node->value.i == i) return 1; + break; + case MDB_GT: + if (node->value.i < i) return 1; + break; + case MDB_LT: + if (node->value.i > i) return 1; + break; + case MDB_GTEQ: + if (node->value.i <= i) return 1; + break; + case MDB_LTEQ: + if (node->value.i >= i) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to mdb_test_int() for operator %d\n",node->op); + break; + } + return 0; +} +#if 0 +#endif +int +mdb_find_indexable_sargs(MdbSargNode *node, gpointer data) +{ + MdbSarg sarg; + + if (node->op == MDB_OR || node->op == MDB_NOT) return 1; + + /* + * right now all we do is look for sargs that are anded together from + * the root. Later we may put together OR ops into a range, and then + * range scan the leaf pages. That is col1 = 2 or col1 = 4 becomes + * col1 >= 2 and col1 <= 4 for the purpose of index scans, and then + * extra rows are thrown out when the row is tested against the main + * sarg tree. range scans are generally only a bit better than table + * scanning anyway. + * + * also, later we should support the NOT operator, but it's generally + * a pretty worthless test for indexes, ie NOT col1 = 3, we are + * probably better off table scanning. + */ + if (mdb_is_relational_op(node->op) && node->col) { + //printf("op = %d value = %s\n", node->op, node->value.s); + sarg.op = node->op; + sarg.value = node->value; + mdb_add_sarg(node->col, &sarg); + } + return 0; +} +int +mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field) +{ +char tmpbuf[256]; +int lastchar; + + if (node->op == MDB_ISNULL) { + if (field->is_null) return 0; + else return 1; + } else if (node->op == MDB_NOTNULL) { + if (field->is_null) return 1; + else return 0; + } + switch (col->col_type) { + case MDB_BOOL: + return mdb_test_int(node, !field->is_null); + break; + case MDB_BYTE: + return mdb_test_int(node, (gint32)((char *)field->value)[0]); + break; + case MDB_INT: + return mdb_test_int(node, (gint32)mdb_get_int16(field->value, 0)); + break; + case MDB_LONGINT: + return mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0)); + break; + case MDB_TEXT: + if (IS_JET4(mdb)) { + mdb_unicode2ascii(mdb, field->value, 0, field->siz, tmpbuf); + } else { + strncpy(tmpbuf, field->value, 255); + lastchar = field->siz > 255 ? 255 : field->siz; + tmpbuf[lastchar]='\0'; + } + return mdb_test_string(node, tmpbuf); + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to mdb_test_sarg() for type %d\n",col->col_type); + break; + } + return 1; +} +int +mdb_find_field(int col_num, MdbField *fields, int num_fields) +{ + int i; + + for (i=0;iop)) { + col = node->col; + /* for const = const expressions */ + if (!col) { + return (node->value.i); + } + elem = mdb_find_field(col->col_num, fields, num_fields); + if (!mdb_test_sarg(mdb, col, node, &fields[elem])) + return 0; + } else { /* logical op */ + switch (node->op) { + case MDB_NOT: + rc = mdb_test_sarg_node(mdb, node->left, fields, num_fields); + return !rc; + break; + case MDB_AND: + if (!mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 0; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + case MDB_OR: + if (mdb_test_sarg_node(mdb, node->left, fields, num_fields)) + return 1; + return mdb_test_sarg_node(mdb, node->right, fields, num_fields); + break; + } + } + return 1; +} +int +mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields) +{ + MdbSargNode *node; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + node = table->sarg_tree; + + /* there may not be a sarg tree */ + if (!node) return 1; + + return mdb_test_sarg_node(mdb, node, fields, num_fields); +} +#if 0 +int mdb_test_sargs(MdbHandle *mdb, MdbColumn *col, int offset, int len) +{ +MdbSarg *sarg; +int i; + + for (i=0;inum_sargs;i++) { + sarg = g_ptr_array_index (col->sargs, i); + if (!mdb_test_sarg(mdb, col, sarg, offset, len)) { + /* sarg didn't match, no sense going on */ + return 0; + } + } + + return 1; +} +#endif +int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg) +{ +MdbSarg *sarg; + if (!col->sargs) { + col->sargs = g_ptr_array_new(); + } + sarg = g_memdup(in_sarg,sizeof(MdbSarg)); + g_ptr_array_add(col->sargs, sarg); + col->num_sargs++; + + return 1; +} +int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg) +{ + MdbColumn *col; + unsigned int i; + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + if (!strcasecmp(col->name,colname)) { + return mdb_add_sarg(col, in_sarg); + } + } + /* else didn't find the column return 0! */ + return 0; +} diff --git a/navit/src/data/poi_geodownload/libmdb/stats.c b/navit/src/data/poi_geodownload/libmdb/stats.c new file mode 100644 index 0000000..1abf285 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/stats.c @@ -0,0 +1,74 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_stats_on: + * @mdb: Handle to the (open) MDB file to collect stats on. + * + * Begins collection of statistics on an MDBHandle. + * + * Statistics in LibMDB will track the number of reads from the MDB file. The + * collection of statistics is started and stopped with the mdb_stats_on and + * mdb_stats_off functions. Collected statistics are accessed by reading the + * MdbStatistics structure or calling mdb_dump_stats. + * + */ +void +mdb_stats_on(MdbHandle *mdb) +{ + if (!mdb->stats) + mdb->stats = g_malloc0(sizeof(MdbStatistics)); + + mdb->stats->collect = TRUE; +} +/** + * mdb_stats_off: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Turns off statistics collection. + * + * If mdb_stats_off is not called, statistics will be turned off when handle + * is freed using mdb_close. + **/ +void +mdb_stats_off(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + mdb->stats->collect = FALSE; +} +/** + * mdb_dump_stats: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Dumps current statistics to stdout. + **/ +void +mdb_dump_stats(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + fprintf(stdout, "Physical Page Reads: %lu\n", mdb->stats->pg_reads); +} diff --git a/navit/src/data/poi_geodownload/libmdb/table.c b/navit/src/data/poi_geodownload/libmdb/table.c new file mode 100644 index 0000000..d3afca8 --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/table.c @@ -0,0 +1,368 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +static gint mdb_col_comparer(MdbColumn **a, MdbColumn **b) +{ + if ((*a)->col_num > (*b)->col_num) + return 1; + else if ((*a)->col_num < (*b)->col_num) + return -1; + else + return 0; +} + +unsigned char mdb_col_needs_size(int col_type) +{ + if (col_type == MDB_TEXT) { + return TRUE; + } else { + return FALSE; + } +} + +MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + + table = (MdbTableDef *) g_malloc0(sizeof(MdbTableDef)); + table->entry=entry; + strcpy(table->name, entry->object_name); + + return table; +} +void mdb_free_tabledef(MdbTableDef *table) +{ + if (!table) return; + if (table->is_temp_table) { + unsigned int i; + for (i=0; itemp_table_pages->len; i++) + g_free(g_ptr_array_index(table->temp_table_pages,i)); + g_ptr_array_free(table->temp_table_pages, TRUE); + } + mdb_free_columns(table->columns); + mdb_free_indices(table->indices); + g_free(table->usage_map); + g_free(table->free_usage_map); + g_free(table); +} +MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) +{ + MdbTableDef *table; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + int len, row_start, pg_row; + char *buf; + + table = mdb_alloc_tabledef(entry); + + mdb_read_pg(mdb, entry->table_pg); + if (mdb->pg_buf[0] != 0x02) return NULL; /* not a valid table def page */ + + len = mdb_pg_get_int16(mdb,8); + + table->num_rows = mdb_pg_get_int32(mdb, fmt->tab_num_rows_offset); + table->num_var_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset-2); + table->num_cols = mdb_pg_get_int16(mdb, fmt->tab_num_cols_offset); + table->num_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_idxs_offset); + table->num_real_idxs = mdb_pg_get_int32(mdb, fmt->tab_num_ridxs_offset); + /* grab a copy of the usage map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_usage_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz)); + table->usage_map = g_memdup(buf + row_start, table->map_sz); + if (mdb_get_option(MDB_DEBUG_USAGE)) + buffer_dump(buf, row_start, row_start+table->map_sz-1); + mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d", + pg_row >> 8, pg_row & 0xff, row_start, table->map_sz); + + /* grab a copy of the free space page map */ + pg_row = mdb_pg_get_int32(mdb, fmt->tab_free_map_offset); + mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz)); + table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz); + mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n", + pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz); + + table->first_data_pg = mdb_pg_get_int16(mdb, fmt->tab_first_dpg_offset); + + return table; +} +MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type) +{ + unsigned int i; + MdbCatalogEntry *entry; + + mdb_read_catalog(mdb, obj_type); + + for (i=0; inum_catalog; i++) { + entry = g_ptr_array_index(mdb->catalog, i); + if (!strcasecmp(entry->object_name, table_name)) + return mdb_read_table(entry); + } + + return NULL; +} + +/* +** read the next page if offset is > pg_size +** return true if page was read +*/ +int +read_pg_if(MdbHandle *mdb, int *cur_pos, int offset) +{ + if (*cur_pos + offset >= mdb->fmt->pg_size) { + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + *cur_pos = 8 - (mdb->fmt->pg_size - (*cur_pos)); + return 1; + } + return 0; +} +guint32 +read_pg_if_32(MdbHandle *mdb, int *cur_pos) +{ + unsigned char c[4]; + int i, rc = 0; + + for (i=0;i<4;i++) { + rc += read_pg_if(mdb, cur_pos, i); + c[i] = mdb->pg_buf[(*cur_pos) + i]; + } + return mdb_get_int32(c, 0); +} +guint16 +read_pg_if_16(MdbHandle *mdb, int *cur_pos) +{ + unsigned char low_byte, high_byte; + int rc = 0; + + rc += read_pg_if(mdb, cur_pos, 0); + low_byte = mdb->pg_buf[*cur_pos]; + rc += read_pg_if(mdb, cur_pos, 1); + high_byte = mdb->pg_buf[(*cur_pos) + 1]; + + return (high_byte * 256 + low_byte); +} +guint16 +read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len) +{ + if (*cur_pos + len < mdb->fmt->pg_size) { + memcpy(buf, &mdb->pg_buf[*cur_pos], len); + return 0; + } else { + int half = mdb->fmt->pg_size - *cur_pos; + memcpy(buf, &mdb->pg_buf[*cur_pos], half); + mdb_read_pg(mdb, mdb_pg_get_int32(mdb,4)); + memcpy(buf + half, &mdb->pg_buf[8], len - half); + *cur_pos = 8 - half; + return 1; + } +} + +void mdb_append_column(GPtrArray *columns, MdbColumn *in_col) +{ + g_ptr_array_add(columns, g_memdup(in_col,sizeof(MdbColumn))); +} +void mdb_free_columns(GPtrArray *columns) +{ + unsigned int i; + + if (!columns) return; + for (i=0; ilen; i++) + g_free (g_ptr_array_index(columns, i)); + g_ptr_array_free(columns, TRUE); +} +GPtrArray *mdb_read_columns(MdbTableDef *table) +{ + MdbHandle *mdb = table->entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + MdbColumn *pcol; + unsigned char *col; + unsigned int i; + int cur_pos, name_sz; + + table->columns = g_ptr_array_new(); + + col = (unsigned char *) g_malloc(fmt->tab_col_entry_size); + + cur_pos = fmt->tab_cols_start_offset + + (table->num_real_idxs * fmt->tab_ridx_entry_size); + + /* new code based on patch submitted by Tim Nelson 2000.09.27 */ + + /* + ** column attributes + */ + for (i=0;inum_cols;i++) { +#ifdef MDB_DEBUG + /* printf("column %d\n", i); + buffer_dump(mdb->pg_buf, cur_pos ,cur_pos + 18); */ +#endif + read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size); + cur_pos += fmt->tab_col_entry_size; + pcol = (MdbColumn *) g_malloc0(sizeof(MdbColumn)); + + pcol->col_type = col[0]; + + // col_num_offset == 1 or 5 + pcol->col_num = col[fmt->col_num_offset]; + + //fprintf(stdout,"----- column %d -----\n",pcol->col_num); + // col_var == 3 or 7 + pcol->var_col_num = mdb_get_int16(col, fmt->tab_col_offset_var); + //fprintf(stdout,"var column pos %d\n",pcol->var_col_num); + + // col_var == 5 or 9 + pcol->row_col_num = mdb_get_int16(col, fmt->tab_row_col_num_offset); + //fprintf(stdout,"row column num %d\n",pcol->row_col_num); + + /* FIXME: can this be right in Jet3 and Jet4? */ + if (pcol->col_type == MDB_NUMERIC) { + pcol->col_prec = col[11]; + pcol->col_scale = col[12]; + } + + // col_fixed_offset == 13 or 15 + pcol->is_fixed = col[fmt->col_fixed_offset] & 0x01 ? 1 : 0; + + // col_fixed_offset == 13 or 15 + pcol->fixed_offset = mdb_get_int16(col, fmt->tab_col_offset_fixed); + //fprintf(stdout,"fixed column offset %d\n",pcol->fixed_offset); + //fprintf(stdout,"col type %s\n",pcol->is_fixed ? "fixed" : "variable"); + + if (pcol->col_type != MDB_BOOL) { + // col_size_offset == 16 or 23 + pcol->col_size = mdb_get_int16(col, fmt->col_size_offset); + } else { + pcol->col_size=0; + } + + g_ptr_array_add(table->columns, pcol); + } + + g_free (col); + + /* + ** column names - ordered the same as the column attributes table + */ + for (i=0;inum_cols;i++) { + pcol = g_ptr_array_index(table->columns, i); + + if (IS_JET4(mdb)) { + char *tmp_buf; + name_sz = read_pg_if_16(mdb, &cur_pos); + cur_pos += 2; + tmp_buf = (char *) g_malloc(name_sz); + read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz); + mdb_unicode2ascii(mdb, tmp_buf, 0, name_sz, pcol->name); + g_free(tmp_buf); + cur_pos += name_sz; + } else if (IS_JET3(mdb)) { + read_pg_if(mdb, &cur_pos, 0); + name_sz = mdb->pg_buf[cur_pos]; + cur_pos++; + read_pg_if_n(mdb, pcol->name, &cur_pos, name_sz); + pcol->name[name_sz]='\0'; + cur_pos += name_sz; + } else { + fprintf(stderr,"Unknown MDB version\n"); + } + } + + /* Sort the columns by col_num */ + g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer); + + table->index_start = cur_pos; + return table->columns; +} + +void mdb_table_dump(MdbCatalogEntry *entry) +{ +MdbTableDef *table; +MdbColumn *col; +int coln; +MdbIndex *idx; +MdbHandle *mdb = entry->mdb; +unsigned int i, bitn; +guint32 pgnum; + + table = mdb_read_table(entry); + fprintf(stdout,"definition page = %lu\n",entry->table_pg); + fprintf(stdout,"number of datarows = %d\n",table->num_rows); + fprintf(stdout,"number of columns = %d\n",table->num_cols); + fprintf(stdout,"number of indices = %d\n",table->num_real_idxs); + + mdb_read_columns(table); + mdb_read_indices(table); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + + fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n", + i, col->name, + mdb_get_coltype_string(mdb->default_backend, col->col_type), + col->col_size); + } + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_index_dump(table, idx); + } + if (table->usage_map) { + printf("pages reserved by this object\n"); + printf("usage map pg %" G_GUINT32_FORMAT "\n", + table->map_base_pg); + printf("free map pg %" G_GUINT32_FORMAT "\n", + table->freemap_base_pg); + pgnum = mdb_get_int32(table->usage_map,1); + /* the first 5 bytes of the usage map mean something */ + coln = 0; + for (i=5;imap_sz;i++) { + for (bitn=0;bitn<8;bitn++) { + if (table->usage_map[i] & 1 << bitn) { + coln++; + printf("%6" G_GUINT32_FORMAT, pgnum); + if (coln==10) { + printf("\n"); + coln = 0; + } else { + printf(" "); + } + } + pgnum++; + } + } + printf("\n"); + } +} + +int mdb_is_user_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && !(entry->flags & 0x80000002)) ? 1 : 0; +} +int mdb_is_system_table(MdbCatalogEntry *entry) +{ + return ((entry->object_type == MDB_TABLE) + && (entry->flags & 0x80000002)) ? 1 : 0; +} diff --git a/navit/src/data/poi_geodownload/libmdb/worktable.c b/navit/src/data/poi_geodownload/libmdb/worktable.c new file mode 100644 index 0000000..6f893dc --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/worktable.c @@ -0,0 +1,99 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2004 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/* + * Temp table routines. These are currently used to generate mock results for + * commands like "list tables" and "describe table" + */ + +void +mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed) +{ + memset(tcol,0,sizeof(MdbColumn)); + strcpy(tcol->name, col_name); + tcol->col_type = col_type; + if ((col_type == MDB_TEXT) || (col_type == MDB_MEMO)) { + tcol->col_size = col_size; + } else { + tcol->col_size = mdb_col_fixed_size(tcol); + } + tcol->is_fixed = is_fixed; +} +void +mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int colnum) +{ + field->value = value; + field->siz = siz; + field->is_fixed = is_fixed; + field->is_null = is_null; + field->start = start; + field->colnum = colnum; +} +MdbTableDef * +mdb_create_temp_table(MdbHandle *mdb, char *name) +{ + MdbCatalogEntry *entry; + MdbTableDef *table; + + /* dummy up a catalog entry */ + entry = (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); + entry->mdb = mdb; + entry->object_type = MDB_TABLE; + entry->table_pg = 0; + strcpy(entry->object_name, name); + + table = mdb_alloc_tabledef(entry); + table->columns = g_ptr_array_new(); + table->is_temp_table = 1; + table->temp_table_pages = g_ptr_array_new(); + + return table; +} +void +mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col) +{ + col->col_num = table->num_cols; + if (!col->is_fixed) + col->var_col_num = table->num_var_cols++; + g_ptr_array_add(table->columns, g_memdup(col, sizeof(MdbColumn))); + table->num_cols++; +} +/* + * Should be called after setting up all temp table columns + */ +void mdb_temp_columns_end(MdbTableDef *table) +{ + MdbColumn *col; + unsigned int i; + unsigned int start = 0; + + for (i=0; inum_cols; i++) { + col = g_ptr_array_index(table->columns, i); + if (col->is_fixed) { + col->fixed_offset = start; + start += col->col_size; + } + } +} diff --git a/navit/src/data/poi_geodownload/libmdb/write.c b/navit/src/data/poi_geodownload/libmdb/write.c new file mode 100644 index 0000000..1cff96a --- /dev/null +++ b/navit/src/data/poi_geodownload/libmdb/write.c @@ -0,0 +1,878 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" +#include "time.h" +#include "math.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +//static int mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg); +static int mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields); + +void +_mdb_put_int16(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; +} +void +_mdb_put_int32(unsigned char *buf, guint32 offset, guint32 value) +{ + buf[offset] = value % 256; + value /= 256; + buf[offset+1] = value % 256; + value /= 256; + buf[offset+2] = value % 256; + value /= 256; + buf[offset+3] = value % 256; +} +ssize_t +mdb_write_pg(MdbHandle *mdb, unsigned long pg) +{ + ssize_t len; + struct stat status; + off_t offset = pg * mdb->fmt->pg_size; + + fstat(mdb->f->fd, &status); + /* is page beyond current size + 1 ? */ + if (status.st_size < offset + mdb->fmt->pg_size) { + fprintf(stderr,"offset %lu is beyond EOF\n",offset); + return 0; + } + lseek(mdb->f->fd, offset, SEEK_SET); + len = write(mdb->f->fd,mdb->pg_buf,mdb->fmt->pg_size); + if (len==-1) { + perror("write"); + return 0; + } else if (lenfmt->pg_size) { + /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->pg_size); */ + return 0; + } + mdb->cur_pos = 0; + return len; +} + +static int +mdb_is_col_indexed(MdbTableDef *table, int colnum) +{ + unsigned int i, j; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + for (j=0;jnum_keys;j++) { + if (idx->key_col_num[j]==colnum) return 1; + } + } + return 0; +} +static int +mdb_crack_row4(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols=0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = mdb_pg_get_int16(mdb, row_start); + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = mdb_pg_get_int16(mdb, row_end - bitmask_sz - 1); + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + for (i=0; inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 2; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + /* Use col->var_col_num because a deleted column is still + * present in the variable column offsets table for the row */ + } else if ((!fields[i].is_fixed) + && (col->var_col_num < row_var_cols)) { + col_start = var_col_offsets[col->var_col_num]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[(col->var_col_num)+1] - + col_start; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +static int +mdb_crack_row3(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + unsigned char *pg_buf = mdb->pg_buf; + unsigned int i; + unsigned int row_var_cols = 0, row_fixed_cols, row_cols; + unsigned int fixed_cols_found, var_cols_found; + unsigned int col_start; + unsigned char *nullmask; + unsigned int bitmask_sz; + unsigned int byte_num, bit_num; + unsigned int *var_col_offsets = NULL; + unsigned int num_jumps = 0, jumps_used = 0; + unsigned int col_ptr, row_len; + + if (mdb_get_option(MDB_DEBUG_ROW)) { + buffer_dump(pg_buf, row_start, row_end); + } + + row_cols = pg_buf[row_start]; + + bitmask_sz = (row_cols + 7) / 8; + nullmask = &pg_buf[row_end - bitmask_sz + 1]; + + /* read table of variable column locations */ + if (table->num_var_cols > 0) { + row_var_cols = pg_buf[row_end - bitmask_sz]; + row_len = row_end - row_start + 1; + num_jumps = (row_len - 1) / 256; + col_ptr = row_end - bitmask_sz - num_jumps - 1; + /* If last jump is a dummy value, ignore it */ + if ((col_ptr-row_start-row_var_cols)/256 < num_jumps) + num_jumps--; + + var_col_offsets = (int *)g_malloc((row_var_cols+1)*sizeof(int)); + jumps_used = 0; + for (i=0; inum_cols;i++) { + col = g_ptr_array_index (table->columns, i); + fields[i].colnum = i; + fields[i].is_fixed = (mdb_is_fixed_col(col)) ? 1 : 0; + byte_num = col->col_num / 8; + bit_num = col->col_num % 8; + /* logic on nulls is reverse, 1 is not null, 0 is null */ + fields[i].is_null = nullmask[byte_num] & (1 << bit_num) ? 0 : 1; + + if ((fields[i].is_fixed) + && (fixed_cols_found < row_fixed_cols)) { + col_start = col->fixed_offset + 1; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = col->col_size; + fixed_cols_found++; + } else if ((!fields[i].is_fixed) + && (var_cols_found < row_var_cols)) { + col_start = var_col_offsets[var_cols_found]; + fields[i].start = row_start + col_start; + fields[i].value = &pg_buf[row_start + col_start]; + fields[i].siz = var_col_offsets[var_cols_found+1] - + col_start; + var_cols_found++; + } else { + fields[i].start = 0; + fields[i].value = NULL; + fields[i].siz = 0; + fields[i].is_null = 1; + } + } + g_free(var_col_offsets); + + return row_cols; +} +/** + * mdb_crack_row: + * @table: Table that the row belongs to + * @row_start: offset to start of row on current page + * @row_end: offset to end of row on current page + * @fields: pointer to MdbField array to be popluated by mdb_crack_row + * + * Cracks a row buffer apart into its component fields. + * + * A row buffer is that portion of a data page which contains the values for + * that row. Its beginning and end can be found in the row offset table. + * + * The resulting MdbField array contains pointers into the row for each field + * present. Be aware that by modifying field[]->value, you would be modifying + * the row buffer itself, not a copy. + * + * This routine is mostly used internally by mdb_fetch_row() but may have some + * applicability for advanced application programs. + * + * Return value: number of fields present. + */ +int +mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; + + if (IS_JET4(mdb)) { + return mdb_crack_row4(table, row_start, row_end, fields); + } else { + return mdb_crack_row3(table, row_start, row_end, fields); + } +} + +static int +mdb_pack_null_mask(unsigned char *buffer, int num_fields, MdbField *fields) +{ + int pos = 0, bit = 0, byte = 0; + int i; + + /* 'Not null' bitmap */ + for (i=0; i> 8) & 0xff; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i> 8) & 0xff; + pos += 2; + + /* Offsets of the variable-length columns */ + for (i=num_fields; i>0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + row_buffer[pos++] = (fields[i-1].offset >> 8) & 0xff; + } + } + /* Number of variable-length columns */ + row_buffer[pos++] = var_cols & 0xff; + row_buffer[pos++] = (var_cols >> 8) & 0xff; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} + +static int +mdb_pack_row3(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields) +{ + unsigned int pos = 0; + unsigned int var_cols = 0; + unsigned int i, j; + unsigned char *offset_high; + + row_buffer[pos++] = num_fields; + + /* Fixed length columns */ + for (i=0;inum_var_cols == 0) { + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; + } + /* Variable length columns */ + for (i=0;i0; i--) { + if (!fields[i-1].is_fixed) { + row_buffer[pos++] = fields[i-1].offset & 0xff; + offset_high[j++] = (fields[i-1].offset << 8) & 0xff; + } + } + + /* Dummy jump table entry */ + if (offset_high[0] < (pos+(num_fields+7)/8-1)/255) { + row_buffer[pos++] = 0xff; + } + /* Jump table */ + for (i=0; i offset_high[i+1]) { + row_buffer[pos++] = var_cols-i; + } + } + g_free(offset_high); + + row_buffer[pos++] = var_cols; + + pos += mdb_pack_null_mask(&row_buffer[pos], num_fields, fields); + return pos; +} +int +mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, int unsigned num_fields, MdbField *fields) +{ + if (table->is_temp_table) { + unsigned int i; + for (i=0; icolumns, i); + fields[i].is_null = (fields[i].value) ? 0 : 1; + fields[i].colnum = i; + fields[i].is_fixed = c->is_fixed; + if ((c->col_type != MDB_TEXT) + && (c->col_type != MDB_MEMO)) { + fields[i].siz = c->col_size; + } + } + } + if (IS_JET4(table->entry->mdb)) { + return mdb_pack_row4(table, row_buffer, num_fields, fields); + } else { + return mdb_pack_row3(table, row_buffer, num_fields, fields); + } +} +int +mdb_pg_get_freespace(MdbHandle *mdb) +{ + int rows, free_start, free_end; + int row_count_offset = mdb->fmt->row_count_offset; + + rows = mdb_pg_get_int16(mdb, row_count_offset); + free_start = row_count_offset + 2 + (rows * 2); + free_end = mdb_pg_get_int16(mdb, row_count_offset + (rows * 2)); + mdb_debug(MDB_DEBUG_WRITE,"free space left on page = %d", free_end - free_start); + return (free_end - free_start); +} +unsigned char * +mdb_new_leaf_pg(MdbCatalogEntry *entry) +{ + MdbHandle *mdb = entry->mdb; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(mdb->fmt->pg_size); + + new_pg[0]=0x04; + new_pg[1]=0x01; + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} +unsigned char * +mdb_new_data_pg(MdbCatalogEntry *entry) +{ + MdbFormatConstants *fmt = entry->mdb->fmt; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(fmt->pg_size); + + new_pg[0]=0x01; + new_pg[1]=0x01; + _mdb_put_int16(new_pg, 2, fmt->pg_size - fmt->row_count_offset - 2); + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} + +int +mdb_update_indexes(MdbTableDef *table, int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + unsigned int i; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); + mdb_debug(MDB_DEBUG_WRITE,"Updating %s (%d).", idx->name, idx->index_type); + if (idx->index_type==1) { + mdb_update_index(table, idx, num_fields, fields, pgnum, rownum); + } + } + return 1; +} + +int +mdb_init_index_chain(MdbTableDef *table, MdbIndex *idx) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + + table->scan_idx = idx; + table->chain = g_malloc0(sizeof(MdbIndexChain)); + table->mdbidx = mdb_clone_handle(mdb); + mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); + + return 1; +} + +int +mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + int idx_xref[16]; + unsigned int i, j; + MdbIndexChain *chain; + MdbField idx_fields[10]; + + for (i = 0; i < idx->num_keys; i++) { + for (j = 0; j < num_fields; j++) { + // key_col_num is 1 based, can't remember why though + if (fields[j].colnum == idx->key_col_num[i]-1) { + idx_xref[i] = j; + idx_fields[i] = fields[j]; + } + } + } + for (i = 0; i < idx->num_keys; i++) { + fprintf(stdout, "key col %d (%d) is mapped to field %d (%d %d)\n", + i, idx->key_col_num[i], idx_xref[i], fields[idx_xref[i]].colnum, + fields[idx_xref[i]].siz); + } + for (i = 0; i < num_fields; i++) { + fprintf(stdout, "%d (%d %d)\n", + i, fields[i].colnum, + fields[i].siz); + } + + chain = g_malloc0(sizeof(MdbIndexChain)); + + mdb_index_find_row(mdb, idx, chain, pgnum, rownum); + printf("chain depth = %d\n", chain->cur_depth); + printf("pg = %" G_GUINT32_FORMAT "\n", + chain->pages[chain->cur_depth-1].pg); + //mdb_copy_index_pg(table, idx, &chain->pages[chain->cur_depth-1]); + mdb_add_row_to_leaf_pg(table, idx, &chain->pages[chain->cur_depth-1], idx_fields); + + return 1; +} + +int +mdb_insert_row(MdbTableDef *table, int num_fields, MdbField *fields) +{ + int new_row_size; + unsigned char row_buffer[4096]; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + guint32 pgnum; + guint16 rownum; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(row_buffer, 0, new_row_size-1); + } + pgnum = mdb_map_find_next_freepage(table, new_row_size); + if (!pgnum) { + fprintf(stderr, "Unable to allocate new page.\n"); + return 0; + } + + rownum = mdb_add_row_to_pg(table, row_buffer, new_row_size); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE, "writing page %d", pgnum); + if (!mdb_write_pg(mdb, pgnum)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + + mdb_update_indexes(table, num_fields, fields, pgnum, rownum); + + return 1; +} +/* + * Assumes caller has verfied space is available on page and adds the new + * row to the current pg_buf. + */ +guint16 +mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size) +{ + unsigned char *new_pg; + int num_rows, i, pos, row_start, row_end, row_size; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + + if (table->is_temp_table) { + GPtrArray *pages = table->temp_table_pages; + if (pages->len == 0) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } else { + new_pg = g_ptr_array_index(pages, pages->len - 1); + if (mdb_get_int16(new_pg, 2) < new_row_size + 2) { + new_pg = mdb_new_data_pg(entry); + g_ptr_array_add(pages, new_pg); + } + } + + num_rows = mdb_get_int16(new_pg, fmt->row_count_offset); + pos = (num_rows == 0) ? fmt->pg_size : + mdb_get_int16(new_pg, fmt->row_count_offset + (num_rows*2)); + } else { /* is not a temp table */ + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + pos = fmt->pg_size; + + /* copy existing rows */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + } + + /* add our new row */ + pos -= new_row_size; + memcpy(&new_pg[pos], row_buffer, new_row_size); + /* add row to the row offset table */ + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); + + /* update number rows on this page */ + num_rows++; + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + /* update the freespace */ + _mdb_put_int16(new_pg,2,pos - fmt->row_count_offset - 2 - (num_rows*2)); + + /* copy new page over old */ + if (!table->is_temp_table) { + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + g_free(new_pg); + } + + return num_rows; +} +int +mdb_update_row(MdbTableDef *table) +{ +int row_start, row_end; +unsigned int i; +MdbColumn *col; +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +MdbField fields[256]; +unsigned char row_buffer[4096]; +int old_row_size, new_row_size, delta; +unsigned int num_fields; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + row_start = mdb_pg_get_int16(mdb, (fmt->row_count_offset + 2) + ((table->cur_row-1)*2)); + row_end = mdb_find_end_of_row(mdb, table->cur_row-1); + old_row_size = row_end - row_start; + + row_start &= 0x0FFF; /* remove flags */ + + mdb_debug(MDB_DEBUG_WRITE,"page %lu row %d start %d end %d", (unsigned long) table->cur_phys_pg, table->cur_row-1, row_start, row_end); + if (mdb_get_option(MDB_DEBUG_LIKE)) + buffer_dump(mdb->pg_buf, row_start, row_end); + + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr && mdb_is_col_indexed(table,i)) { + fprintf(stderr, "Attempting to update column that is part of an index\n"); + return 0; + } + } + num_fields = mdb_crack_row(table, row_start, row_end, fields); + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + for (i=0;inum_cols;i++) { + col = g_ptr_array_index(table->columns,i); + if (col->bind_ptr) { + printf("yes\n"); + fields[i].value = col->bind_ptr; + fields[i].siz = *(col->len_ptr); + } + } + + new_row_size = mdb_pack_row(table, row_buffer, num_fields, fields); + if (mdb_get_option(MDB_DEBUG_WRITE)) + buffer_dump(row_buffer, 0, new_row_size-1); + delta = new_row_size - old_row_size; + if ((mdb_pg_get_freespace(mdb) - delta) < 0) { + fprintf(stderr, "No space left on this page, update will not occur\n"); + return 0; + } + /* do it! */ + mdb_replace_row(table, table->cur_row-1, row_buffer, new_row_size); + return 0; +} +int +mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size) +{ +MdbCatalogEntry *entry = table->entry; +MdbHandle *mdb = entry->mdb; +MdbFormatConstants *fmt = mdb->fmt; +unsigned char *new_pg; +guint16 num_rows; +int row_start, row_end, row_size; +int i, pos; + + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + mdb_debug(MDB_DEBUG_WRITE,"updating row %d on page %lu", row, (unsigned long) table->cur_phys_pg); + new_pg = mdb_new_data_pg(entry); + + num_rows = mdb_pg_get_int16(mdb, fmt->row_count_offset); + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + pos = mdb->fmt->pg_size; + + /* rows before */ + for (i=0;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* our row */ + pos -= new_row_size; + memcpy(&new_pg[pos], new_row, new_row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (row*2), pos); + + /* rows after */ + for (i=row+1;irow_count_offset + 2) + (i*2)); + row_end = mdb_find_end_of_row(mdb, i); + row_size = row_end - row_start + 1; + pos -= row_size; + memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + } + + /* almost done, copy page over current */ + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + + g_free(new_pg); + + _mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); + if (mdb_get_option(MDB_DEBUG_WRITE)) { + buffer_dump(mdb->pg_buf, 0, 39); + buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); + } + /* drum roll, please */ + if (!mdb_write_pg(mdb, table->cur_phys_pg)) { + fprintf(stderr, "write failed! exiting...\n"); + exit(1); + } + return 0; +} +static int +mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg, MdbField *idx_fields) +/*, guint32 pgnum, guint16 rownum) +static int +mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndexPage *ipg) +*/ +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbColumn *col; + guint32 pg; + guint16 row; + unsigned char *new_pg; + unsigned char key_hash[256]; + unsigned char iflag; + int keycol; + + new_pg = mdb_new_leaf_pg(entry); + + mdb_index_page_reset(ipg); + mdb_read_pg(mdb, ipg->pg); + + /* do we support this index type yet? */ + if (idx->num_keys > 1) { + fprintf(stderr,"multikey indexes not yet supported, aborting\n"); + return 0; + } + keycol = idx->key_col_num[0]; + col = g_ptr_array_index (table->columns, keycol - 1); + printf("keycol = %d (%s)\n", keycol, col->name); + if (!mdb_is_fixed_col(col)) { + fprintf(stderr,"variable length key columns not yet supported, aborting\n"); + return 0; + } + printf("col size = %d\n", col->col_size); + + while (mdb_index_find_next_on_page(mdb, ipg)) { + + /* check for compressed indexes. */ + if (ipg->len < col->col_size + 1) { + fprintf(stderr,"compressed indexes not yet supported, aborting\n"); + return 0; + } + + pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4); + row = mdb->pg_buf[ipg->offset + ipg->len - 1]; + iflag = mdb->pg_buf[ipg->offset]; + mdb_index_swap_n(&mdb->pg_buf[ipg->offset + 1], col->col_size, key_hash); + key_hash[col->col_size - 1] &= 0x7f; + printf("length = %d\n", ipg->len); + printf("iflag = %d pg = %" G_GUINT32_FORMAT + " row = %" G_GUINT16_FORMAT "\n", iflag, pg, row); + buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset + ipg->len - 1); + buffer_dump(mdb->pg_buf, ipg->offset + 1, ipg->offset + col->col_size); + buffer_dump(key_hash, 0, col->col_size - 1); + ipg->offset += ipg->len; + ipg->len = 0; + row++; + } + g_free(new_pg); + + return ipg->len; +} diff --git a/navit/src/data/poi_geodownload/poi_geodownload.c b/navit/src/data/poi_geodownload/poi_geodownload.c new file mode 100644 index 0000000..8062ca5 --- /dev/null +++ b/navit/src/data/poi_geodownload/poi_geodownload.c @@ -0,0 +1,661 @@ +#include +#include "debug.h" +#include "coord.h" +#include "map.h" +#include "item.h" +#include "projection.h" +#include "plugin.h" + + +#include +#include +#include + +struct map_priv +{ + char *filename; + MdbHandle *h; + MdbHandle *h_idx; + MdbTableDef *table; + GPtrArray *table_col; + MdbColumn **cols; + MdbIndex *idx; + int idx_size; + enum item_type type; +}; + +struct map_rect_priv +{ + struct item item; + struct map_priv *m; + int cidx; +}; + +#if 0 +struct index_data { + unsigned char data[15]; +}; +struct poi { + char filename[1024]; + char icon[1024]; + long pos; + MdbHandle *h; + MdbHandle *h_idx; + MdbTableDef *table; + GPtrArray *table_col; + MdbColumn **cols; + MdbIndex *idx; + int idx_size; + struct index_data index_data; + MdbIndexChain chain; + struct poi *next; +} *poi_list; + +struct poi_data { + struct poi *poi; + int page; + int row; +}; + + char poipath[256]; + char poibmp[256]; + + +static void +print_col(MdbHandle *h, MdbColumn *col, char *buffer, int hex) +{ + switch (col->col_type) { + case MDB_BOOL: + strcpy(buffer, mdb_pg_get_byte(h, col->cur_value_start) ? "True" : "False"); + break; + case MDB_BYTE: + sprintf(buffer, "%d", mdb_pg_get_byte(h, col->cur_value_start)); + break; + case MDB_LONGINT: + if (hex) + sprintf(buffer, "0x%lx", mdb_pg_get_int32(h, col->cur_value_start)); + else + sprintf(buffer, "%ld", mdb_pg_get_int32(h, col->cur_value_start)); + break; + case MDB_DOUBLE: + sprintf(buffer, "%f", mdb_pg_get_double(h, col->cur_value_start)); + break; + case MDB_TEXT: + sprintf(buffer, "%s", mdb_col_to_string (h, h->pg_buf, col-> cur_value_start, + col->col_type, col->cur_value_len)); + break; + default: + sprintf(buffer, "unknown (%d)", col->col_type); + } +} + +static void +setup_idx_data(struct index_data *idx, struct coord *c, unsigned int geoflags, int size) +{ + /* 7f 80 1c 91 0a 7f 80 5c f5 41 7f 80 00 00 05 */ + idx->data[0]=0x7f; + idx->data[1]=(c->x >> 24) ^ 0x80; + idx->data[2]=c->x >> 16; + idx->data[3]=c->x >> 8; + idx->data[4]=c->x; + idx->data[5]=0x7f; + idx->data[6]=(c->y >> 24) ^ 0x80; + idx->data[7]=c->y >> 16; + idx->data[8]=c->y >> 8; + idx->data[9]=c->y; + idx->data[10]=0x7f; + if (size > 12) { + idx->data[11]=0x80 | (geoflags >> 24); + idx->data[12]=geoflags >> 16; + idx->data[13]=geoflags >> 8; + idx->data[14]=geoflags; + } else { + idx->data[11]=geoflags; + } +} + +static void +setup_idx_rect(struct coord *rect, struct index_data *idx, int size) +{ + struct coord r[2]; + r[0].x=rect[0].x; + r[0].y=rect[1].y; + r[1].x=rect[1].x; + r[1].y=rect[0].y; +#if 0 + printf("low 0x%x 0%x\n", r[0].x, r[0].y); + printf("high 0x%x 0%x\n", r[1].x, r[1].y); +#endif + setup_idx_data(idx, r, 0, size); + setup_idx_data(idx+1, r+1, 0xffffffff, size); +} + +static int +load_row(struct poi *poi, int pg, int row) +{ + int row_start, row_end, offset; + unsigned int num_fields, i; + MdbField fields[256]; + MdbFormatConstants *fmt; + int debug=0; + + fmt=poi->h->fmt; + mdb_read_pg(poi->h, pg); + if (debug) + printf("Page Type %d row_count_offset %d\n",poi->h->pg_buf[0], fmt->row_count_offset); + if (debug > 1) { + for (i = 0; i <= row; i++) { + offset=(fmt->row_count_offset + 2) + i * 2; + printf("row %d %d 0x%x\n", i, offset, mdb_pg_get_int16(poi->h, offset)); + } + } + row_start = mdb_pg_get_int16(poi->h, (fmt->row_count_offset + 2) + row * 2); + if (row_start & 0x4000) + return 1; + row_end = mdb_find_end_of_row(poi->h, row); + if (debug) { + printf("start=0x%x end=0x%x\n", row_start, row_end); + buffer_dump(poi->h->pg_buf, row_start, row_end); + } + + poi->h->cur_pos=row_start & 0x1fff; + poi->table->cur_row=row+1; + num_fields = mdb_crack_row(poi->table, row_start & 0x1fff, row_end, fields); + if (debug) + printf("num_fields=%d\n", num_fields); + for (i = 0; i < num_fields; i++) { + poi->cols[i]->cur_value_start=fields[i].start; + poi->cols[i]->cur_value_len=fields[i].siz; + } + return 0; +} + +static MdbIndexPage * +index_next_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain) +{ + MdbIndexPage *ipg; + + ipg = mdb_index_read_bottom_pg(mdb, idx, chain); + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no next\n"); +#endif + if (!chain->clean_up_mode) { +#if 0 + printf("no cleanup\n"); +#endif + if (!(ipg = mdb_index_unwind(mdb, idx, chain))) + chain->clean_up_mode = 1; + } + if (chain->clean_up_mode) { +#if 0 + printf("cleanup\n"); +#endif + //fprintf(stdout,"in cleanup mode\n"); + + if (!chain->last_leaf_found) { + printf("no last_leaf_found\n"); + return NULL; + } + mdb_read_pg(mdb, chain->last_leaf_found); + chain->last_leaf_found = + mdb_pg_get_int24(mdb, 0x0c); + //printf("next leaf %lu\n", chain->last_leaf_found); + mdb_read_pg(mdb, chain->last_leaf_found); + /* reuse the chain for cleanup mode */ + chain->cur_depth = 1; + ipg = &chain->pages[0]; + mdb_index_page_init(ipg); + ipg->pg = chain->last_leaf_found; + //printf("next on page %d\n", + if (!mdb_index_find_next_on_page(mdb, ipg)) { +#if 0 + printf("no find_next_on_page\n"); +#endif + return NULL; + } + } + } + return ipg; +} + +static int +index_next(struct poi *poi, struct index_data *idx) +{ + MdbIndexPage *ipg; + MdbIndexChain *chain = &poi->chain; + int row; + int pg; + int offset; + char *cmp, *low, *high; + int debug=0; + + + for(;;) { + for(;;) { + ipg=index_next_row(poi->h_idx, poi->idx, chain); + if (! ipg) + return 0; + row = poi->h_idx->pg_buf[ipg->offset + ipg->len - 1]; + pg = mdb_pg_get_int24_msb(poi->h_idx, ipg->offset + ipg->len - 4); + + offset=poi->idx_size+4-ipg->len; + memcpy(poi->index_data.data+offset, poi->h_idx->pg_buf+ipg->offset, ipg->len - 4); + cmp=poi->index_data.data; + low=idx[0].data; + high=idx[1].data; + if (debug > 1) { + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } +#if 0 + buffer_dump(poi->h_idx->pg_buf, ipg->offset, ipg->offset+ipg->len-1); +#endif + ipg->offset += ipg->len; + if (memcmp(cmp, low, poi->idx_size) >= 0) { + if (memcmp(cmp, high, poi->idx_size) <=0 ) { + if (debug) { + printf("match\n"); + buffer_dump(low, 0, poi->idx_size-1); + buffer_dump(cmp, 0, poi->idx_size-1); + buffer_dump(high, 0, poi->idx_size-1); + printf("%d %d %d\n", memcmp(cmp, low, poi->idx_size), memcmp(cmp, high, poi->idx_size), offset); + } + break; + } else { + return 0; + } + } + if (debug > 1) + printf("row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + } + if (debug) + printf("match: row=0x%x pg=0x%x len=%d\n", row, pg, ipg->len); + if (!load_row(poi, pg, row)) + break; + } + return 1; +} + +#endif + +static int +load_poi_table(struct map_priv *m, MdbCatalogEntry *entry) +{ + int j; + MdbIndex *idx; + + m->h_idx=NULL; + m->table = mdb_read_table(entry); + m->table_col = mdb_read_columns(m->table); + mdb_read_indices(m->table); + m->cols = (MdbColumn **) (m->table_col->pdata); + if (m->table_col->len < 4 || strcasecmp(m->cols[0]->name, "X") || + strcasecmp(m->cols[1]->name, "Y") || strcasecmp(m->cols[3]->name, "GEOFLAGS")) + return 1; + for (j = 0; j < m->table->num_idxs; j++) { + idx = m->table->indices->pdata[j]; + if (idx->num_keys == 3 && idx->key_col_num[0] == 1 && + idx->key_col_num[1] == 2 && idx->key_col_num[2] == 4) { + m->idx = idx; + m->idx_size=3+m->cols[0]->col_size+m->cols[1]->col_size+m->cols[3]->col_size; + m->h_idx=mdb_clone_handle(m->h); + } + } + return 0; +} + +#if 0 + +static void +load_poi(char *filename, char *icon, int type) +{ + int i; + MdbCatalogEntry *entry; + GPtrArray *catalog; + struct poi *new = g_new0(struct poi, 1); + + FILE *fp = fopen(filename,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : POI file %s does not exists!\n",filename); + exit(0); + return -1; + } + + + fp = fopen(icon,"r"); + if( fp ) { + fclose(fp); + } else { + printf("ERR : WARNING INCORRECT PICTURE! %s!\n",icon); + exit(0); + return -1; + } + + strcpy(new->filename,filename); + strcpy(new->icon,icon); + new->type = type; + + + if (type == 0) { + new->h = mdb_open(filename, MDB_NOFLAGS); + catalog = mdb_read_catalog(new->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(new, entry)) { + printf("%s invalid\n", filename); + g_free(new); + new=NULL; + } + } + } + g_ptr_array_free(catalog, 1); + } + if (new) { + new->next = poi_list; + poi_list = new; + } +} + +static void +get_coord(struct poi *p, struct coord *c) +{ + c->x=mdb_pg_get_int32(p->h, p->cols[0]->cur_value_start); + c->y=mdb_pg_get_int32(p->h, p->cols[1]->cur_value_start); +} + +static void +poi_info(struct display_list *list, struct popup_item **popup) +{ + struct poi_data *data=list->data; + struct poi *poi=data->poi; + struct popup_item *popup_last, *popup_val_last; + char *text,buffer[4096]; + int j; + MdbColumn *col; + char *v; + + popup_last = *popup; + + popup_val_last = NULL; + sprintf(buffer,"File:%s", poi->filename); + popup_item_new_text(&popup_val_last, buffer, 1); + sprintf(buffer,"Icon:%s", poi->icon); + popup_item_new_text(&popup_val_last, buffer, 2); + if (poi->type == 0) { + printf("poi_info pg=%d row=%d\n", data->page, data->row); + load_row(poi, data->page, data->row); + sprintf(buffer,"Page:%d", data->page); + popup_item_new_text(&popup_val_last, buffer, 3); + sprintf(buffer,"Row:%d", data->row); + popup_item_new_text(&popup_val_last, buffer, 4); + for (j = 0; j < poi->table_col->len; j++) { + col = poi->table_col->pdata[j]; + #if 0 + printf("start: %d type:%d\n", col->cur_value_start, col->col_type); + #endif + sprintf(buffer, "%s:", col->name); + v = buffer + strlen(buffer); + if (!strcasecmp(col->name,"X") || !strcasecmp(col->name,"Y")) + print_col(poi->h, col, v, 1); + else + print_col(poi->h, col, v, 0); + #if 0 + printf("%s\n", buffer); + #endif + text=g_convert(buffer,-1,"utf-8","iso8859-1",NULL,NULL,NULL); + popup_item_new_text(&popup_val_last, buffer, j+10); + g_free(text); + } + } + popup_item_new_text(&popup_last, "POI", 20)->submenu = popup_val_last; + *popup=popup_last; +} + +static void +draw_poi(struct poi *p, struct container *co, struct point *pnt) +{ + struct poi_data data; + data.poi=p; + if (p->type == 0) { + data.page=p->h->cur_pg; + data.row=p->table->cur_row-1; + } + if (p->type == 1) { + data.row=p->pos; + } + display_add(&co->disp[display_poi], 5, 0, p->icon, 1, pnt, poi_info, &data, sizeof(data)); +} + +static void +plugin_draw(struct container *co) +{ + struct coord c; + struct point pnt; + struct poi *p; + struct index_data idx[2]; + int use_index=0; + int debug=1; + + p = poi_list; + + if (co->trans->scale > 1024) + return; + if (debug) { + printf("scale=%ld\n", co->trans->scale); + printf("rect 0x%lx,0%lx-0x%lx,0x%lx\n", co->trans->rect[0].x, co->trans->rect[0].y, co->trans->rect[1].x, co->trans->rect[1].y); + } + while (p) { + if (p->type == 0) { + if (use_index) + setup_idx_rect(co->trans->rect, idx, p->idx_size); + if (! use_index) { + printf("rewind %s %p\n", p->filename, p->table); + mdb_rewind_table(p->table); + while (mdb_fetch_row(p->table)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } else { + memset(&p->chain, 0, sizeof(p->chain)); + while (index_next(p, idx)) { + get_coord(p, &c); + if (transform(co->trans, &c, &pnt)) { + if (debug) + printf("coord 0x%lx,0x%lx pg %d row %d\n", c.x, c.y, p->h->cur_pg, p->table->cur_row); + draw_poi(p, co, &pnt); + } + } + } + } + if (p->type == 1) { + FILE *f; + char line[1024]; + struct text_poi tpoi; + if(!(f=fopen(p->filename, "r"))){ + printf("can't open poi file for drawing!\n"); + exit(0); + } +#if 0 + printf("opened poi file %s for drawing!\n",p->filename); +#endif + p->pos=ftell(f); + fgets(line, 1024, f); + while (!feof(f)) { + if (strlen(line)) { + line[strlen(line)-1]='\0'; + } + if (parse_text_poi(line, &tpoi)) { + transform_mercator(&tpoi.lat,&tpoi.lng,&c); +// printf("%ld %ld\n", c.x, c.y); + if (transform(co->trans, &c, &pnt)) { + draw_poi(p, co, &pnt); + } + } + p->pos=ftell(f); + fgets(line, 1024, f); + } + fclose(f); + } + p = p->next; + } + +} + +#endif + +static void +map_destroy_poi_geodownload(struct map_priv *m) +{ + dbg(1,"enter\n"); + g_free(m); +} + +static void +poi_geodownload_coord_rewind(void *priv_data) +{ + struct map_rect_priv *mr=priv_data; + mr->cidx=0; +} + + +static int +poi_geodownload_coord_get(void *priv_data, struct coord *c, int count) +{ + struct map_rect_priv *mr=priv_data; + dbg(1,"enter\n"); + if (mr->cidx || !count) + return 0; + c->x=mdb_pg_get_int32(mr->m->h, mr->m->cols[0]->cur_value_start); + c->y=mdb_pg_get_int32(mr->m->h, mr->m->cols[1]->cur_value_start); + dbg(1,"x=0x%x y=0x%x\n", c->x, c->y); + return 1; +} + +static void +poi_geodownload_attr_rewind(void *priv_data) +{ +} + +static int +poi_geodownload_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr) +{ + dbg(1,"enter\n"); + return 0; +} + +static struct item_methods methods_poi_geodownload = { + poi_geodownload_coord_rewind, + poi_geodownload_coord_get, + poi_geodownload_attr_rewind, + poi_geodownload_attr_get, +}; + + +static struct map_rect_priv * +map_rect_new_poi_geodownload(struct map_priv *map, struct map_selection *sel) +{ + struct map_rect_priv *mr; + + dbg(1,"enter\n"); + mr=g_new0(struct map_rect_priv, 1); + mr->item.meth=&methods_poi_geodownload; + mr->item.id_hi=0; + mr->item.id_lo=0; + mr->item.priv_data=mr; + mr->item.type=map->type; + mr->m=map; + mdb_rewind_table(map->table); + return mr; +} + + +static void +map_rect_destroy_poi_geodownload(struct map_rect_priv *mr) +{ + g_free(mr); +} + +static struct item * +map_rect_get_item_poi_geodownload(struct map_rect_priv *mr) +{ + dbg(1,"enter\n"); + if (mdb_fetch_row(mr->m->table)) + return &mr->item; + return NULL; +} + +static struct item * +map_rect_get_item_byid_poi_geodownload(struct map_rect_priv *mr, int id_hi, int id_lo) +{ + return NULL; +} + + +static struct map_methods map_methods_poi_geodownload = { + map_destroy_poi_geodownload, + map_rect_new_poi_geodownload, + map_rect_destroy_poi_geodownload, + map_rect_get_item_poi_geodownload, + map_rect_get_item_byid_poi_geodownload, +}; + +static struct map_priv * +map_new_poi_geodownload(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) +{ + struct map_priv *m; + dbg(1,"filename %s\n",filename); + MdbCatalogEntry *entry; + GPtrArray *catalog; + int i; + struct attr *attr; + + *meth=map_methods_poi_geodownload; + *charset="iso8859-1"; + *pro=projection_mg; + + m=g_new(struct map_priv, 1); + m->filename=g_strdup(filename); + m->h = mdb_open(m->filename, MDB_NOFLAGS); + m->type=type_none; + dbg(1,"attr_search\n"); + attr=attr_search(attrs, NULL, attr_item_type); + dbg(1,"attr_search result %p\n", attr); + if (attr) { + m->type=attr->u.item_type; + printf("type '%s'\n", item_to_name(m->type)); + } + + + catalog = mdb_read_catalog(m->h, MDB_TABLE); + for (i = 0; i < catalog->len; i++) { + entry = catalog->pdata[i]; + dbg(1,"object name '%s'\n", entry->object_name); + if (!strcasecmp(entry->object_name, "_INDEXDATA")) { + if (load_poi_table(m, entry)) { + printf("%s invalid\n", filename); + g_free(m); + m=NULL; + } + } + } + g_ptr_array_free(catalog, 1); + return m; +} + +void +plugin_init(void) +{ + dbg(1,"plugin_init\n"); + plugin_register_map_type("poi_geodownload", map_new_poi_geodownload); +} + diff --git a/navit/src/data/textfile/textfile.c b/navit/src/data/textfile/textfile.c index 908be5b..17e62f8 100644 --- a/navit/src/data/textfile/textfile.c +++ b/navit/src/data/textfile/textfile.c @@ -291,7 +291,7 @@ static struct map_methods map_methods_textfile = { }; static struct map_priv * -map_new_textfile(struct map_methods *meth, char *filename, char **charset, enum projection *pro) +map_new_textfile(struct map_methods *meth, char *filename, struct attr **attrs, char **charset, enum projection *pro) { struct map_priv *m; dbg(1,"map_new_textfile %s\n",filename); diff --git a/navit/src/graphics.c b/navit/src/graphics.c index 593d7f3..7a2f205 100644 --- a/navit/src/graphics.c +++ b/navit/src/graphics.c @@ -466,8 +466,10 @@ do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapset while ((item=map_rect_get_item(mr))) { if (item->type < type_line) { item_coord_get(item, &c, 1); - if (!transform(t, pro, &c, &pnt[0])) + if (!transform(t, pro, &c, &pnt[0])) { + dbg(1,"not visible\n"); continue; + } count=1; } else { count=0; diff --git a/navit/src/gui/gtk/destination.c b/navit/src/gui/gtk/destination.c index 286da7a..6af8b34 100644 --- a/navit/src/gui/gtk/destination.c +++ b/navit/src/gui/gtk/destination.c @@ -7,9 +7,8 @@ #include "debug.h" #include "destination.h" #include "navit.h" -#include "attr.h" -#include "coord.h" #include "item.h" +#include "coord.h" #include "search.h" #define COL_COUNT 8 diff --git a/navit/src/item.c b/navit/src/item.c index 89c5a2e..81ec9b2 100644 --- a/navit/src/item.c +++ b/navit/src/item.c @@ -1,6 +1,5 @@ #include #include -#include "attr.h" #include "coord.h" #include "debug.h" #include "item.h" diff --git a/navit/src/item.h b/navit/src/item.h index 473d8f9..d497f15 100644 --- a/navit/src/item.h +++ b/navit/src/item.h @@ -1,4 +1,3 @@ -#include "attr.h" enum item_type { @@ -9,6 +8,8 @@ enum item_type { #undef ITEM }; +#include "attr.h" + #define item_is_equal_id(a,b) ((a).id_hi == (b).id_hi && (a).id_lo == (b).id_lo) #define item_is_equal(a,b) (item_is_equal_id(a,b) && (a).map == (b).map) diff --git a/navit/src/item_def.h b/navit/src/item_def.h index 0f771d2..71d3311 100644 --- a/navit/src/item_def.h +++ b/navit/src/item_def.h @@ -89,6 +89,10 @@ ITEM(poi_picnic) ITEM(poi_hospital) ITEM(poi_camping) ITEM(poi_public_utilities) +ITEM(poi_burgerking) +ITEM(poi_kfc) +ITEM(poi_mcdonalds) +ITEM(poi_wienerwald) ITEM2(0x80000000,line) ITEM2(0x80000001,line_unspecified) /* Line */ diff --git a/navit/src/map.c b/navit/src/map.c index a209c14..36bf329 100644 --- a/navit/src/map.c +++ b/navit/src/map.c @@ -26,10 +26,10 @@ struct map_rect { }; struct map * -map_new(const char *type, const char *filename) +map_new(const char *type, const char *filename, struct attr **attrs) { struct map *m; - struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, char **charset, enum projection *pro); + struct map_priv *(*maptype_new)(struct map_methods *meth, const char *name, struct attr *attrs, char **charset, enum projection *pro); maptype_new=plugin_get_map_type(type); if (! maptype_new) @@ -39,7 +39,7 @@ map_new(const char *type, const char *filename) m->active=1; m->filename=g_strdup(filename); m->type=g_strdup(type); - m->priv=maptype_new(&m->meth, filename, &m->charset, &m->projection); + m->priv=maptype_new(&m->meth, filename, attrs, &m->charset, &m->projection); return m; } diff --git a/navit/src/map.h b/navit/src/map.h index c0b9361..9127494 100644 --- a/navit/src/map.h +++ b/navit/src/map.h @@ -28,7 +28,7 @@ struct map; struct map_rect; struct map_search; struct map_selection; -struct map *map_new(const char *type, const char *filename); +struct map *map_new(const char *type, const char *filename, struct attr **attrs); char * map_convert_string(struct map *this, char *str); void map_convert_free(char *str); char *map_get_filename(struct map *this); diff --git a/navit/src/mapset.c b/navit/src/mapset.c index 17fbecf..39cb0d5 100644 --- a/navit/src/mapset.c +++ b/navit/src/mapset.c @@ -1,7 +1,7 @@ #include #include #include "debug.h" -#include "attr.h" +#include "item.h" #include "mapset.h" #include "map.h" diff --git a/navit/src/navit.c b/navit/src/navit.c index 9bb1dd2..652563d 100644 --- a/navit/src/navit.c +++ b/navit/src/navit.c @@ -694,7 +694,7 @@ navit_window_items_open(struct menu *men, struct navit *this_, struct navit_wind if (item_coord_get(item, &c, 1)) { if (coord_rect_contains(&sel.rect, &c) && g_hash_table_lookup(nwi->hash, &item->type)) { if (! item_attr_get(item, attr_label, &attr)) - attr.u.str=NULL; + attr.u.str=""; idist=transform_distance(center, &c); if (idist < dist) { get_direction(dirbuf, transform_get_angle_delta(center, &c, 0), 1); diff --git a/navit/src/plugin_def.h b/navit/src/plugin_def.h index 075709b..701598d 100644 --- a/navit/src/plugin_def.h +++ b/navit/src/plugin_def.h @@ -1,10 +1,11 @@ enum projection; +struct attr; PLUGIN_FUNC1(draw, struct container *, co) PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list) struct navit; PLUGIN_TYPE(graphics, (struct graphics_methods *meth)) PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, int w, int h)) -PLUGIN_TYPE(map, (struct map_methods *meth, char *data, char **charset, enum projection *pro)) +PLUGIN_TYPE(map, (struct map_methods *meth, char *data, struct attr **attr, char **charset, enum projection *pro)) PLUGIN_TYPE(osd, (struct osd_methods *meth)) PLUGIN_TYPE(speech, (char *data, struct speech_methods *meth)) PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth)) diff --git a/navit/src/search.c b/navit/src/search.c index 8ac9518..3d7e3e0 100644 --- a/navit/src/search.c +++ b/navit/src/search.c @@ -2,7 +2,6 @@ #include "debug.h" #include "map.h" #include "mapset.h" -#include "attr.h" #include "coord.h" #include "item.h" #include "search.h" diff --git a/navit/src/xmlconfig.c b/navit/src/xmlconfig.c index 0eff60b..a2ff462 100644 --- a/navit/src/xmlconfig.c +++ b/navit/src/xmlconfig.c @@ -28,6 +28,33 @@ struct xmlstate { } *xmlstate_root; +static struct attr ** convert_to_attr(struct xmlstate *state) +{ + const gchar **attribute_name=state->attribute_names; + const gchar **attribute_value=state->attribute_values; + int count=0; + struct attr **ret; + + while (*attribute_name) { + count++; + attribute_name++; + } + ret=g_new(struct attr, count+1); + attribute_name=state->attribute_names; + count=0; + while (*attribute_name) { + ret[count]=attr_new_from_text(*attribute_name,*attribute_value); + if (ret[count]) + count++; + attribute_name++; + attribute_value++; + } + ret[count]=NULL; + dbg(0,"ret=%p\n", ret); + return ret; +} + + static const char * find_attribute(struct xmlstate *state, const char *attribute, int required) { const gchar **attribute_name=state->attribute_names; @@ -342,11 +369,13 @@ xmlconfig_mapset(struct xmlstate *state) static int xmlconfig_map(struct xmlstate *state) { + struct attr **attr; const char *type=find_attribute(state, "type", 1); const char *data=find_attribute(state, "data", 1); if (! type || ! data) return 0; - state->element_object = map_new(type, data); + attr=convert_to_attr(state); + state->element_object = map_new(type, data, attr); if (! state->element_object) return 0; if (!find_boolean(state, "active", 1, 0)) -- 2.7.4