You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spOSMroute/mapsys/map_hash.c

306 lines
7.9 KiB

/***************************************************************************
* map_hash.c
*
* Copyright 2009 - Steffen Pohle
* steffen@gulpe.de
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <time.h>
#include "map.h"
#include "memoryleak.h"
#include "system.h"
/*****************************************************
*
* Hash handling
*
*/
struct map_hash *map_hash_alloc (int memsize) {
struct map_hash *mh;
mh = (struct map_hash*) ml_malloc (sizeof (struct map_hash) + memsize);
mh->status = 0;
mh->ways = NULL;
mh->areas = NULL;
mh->places = NULL;
mh->pois = NULL;
mh->free = mh->data;
mh->datasize = memsize;
mh->wayscnt = 0;
mh->poiscnt = 0;
mh->placescnt = 0;
mh->areascnt = 0;
return mh;
};
int map_hash_calc_size (int ways, int areas, int pois, int places, int pcnt, int ncnt, int ccnt) {
return (POINTERALIGNMENT + sizeof (struct map_hash) + ways * (POINTERALIGNMENT + sizeof (struct map_way)) + areas * (POINTERALIGNMENT + sizeof (struct map_area))
+ pcnt * (POINTERALIGNMENT + sizeof (struct map_pos)) + ncnt * (POINTERALIGNMENT + sizeof (struct map_waynode))
+ pois * (POINTERALIGNMENT + sizeof (struct map_poi)) + places * (POINTERALIGNMENT + sizeof (struct map_place)) + ccnt);
};
/******************************************************************************
* find the hash file inside the memory, if we can't find do as the loadflags
* sais, return NULL or load the hash and add it into the map_hash table
*/
struct map_hash *map_hash_get (float lon, float lat, int loadflags) {
return (map_hash_geti (map_geo2igeo(lon), map_geo2igeo(lat), loadflags));
};
struct map_hash *map_hash_geti (int ilon, int ilat, int loadflags) {
struct map_hash *res = NULL;
int hi;
hi = mhash_pos;
if (mhash[hi] && mhash[hi]->pos.ilon == ilon && mhash[hi]->pos.ilat == ilat) res = mhash[hi];
else {
hi = mhash_pos+1;
if (hi >= mhash_max) hi = 0;
while (hi != mhash_pos) {
if (mhash[hi] && mhash[hi]->pos.ilon == ilon && mhash[hi]->pos.ilat == ilat) {
res = mhash[hi];
break;
}
if (++hi >= mhash_max) hi = 0;
}
if (res == NULL && loadflags & MHLOAD_RELOAD) {
res = map_load_hash (ilon, ilat);
if (res) {
if ((--mhash_pos) < 0) mhash_pos = mhash_max-1;
/* add on the givin place, delete old entry */
if (mhash[mhash_pos]) {
map_hash_free (mhash[mhash_pos], 1);
mhash[mhash_pos] = NULL;
}
/* add or update */
if (mhash[mhash_pos] != NULL) d_printf ("%s:%d map_hash_add: memory leak: not free spot", __FILE__, __LINE__);
mhash[mhash_pos] = res;
DELFLAG (res->status, MS_changed);
}
}
}
return res;
};
/******************************************************************************
* add this hash data to the memory.
* if it already excist exchange it and free the old hash data from the memory
*/
int map_hash_add (struct map_hash *mh) {
int i;
struct map_hash *mhold = NULL;
if (mh == NULL) return 0;
/* check if we need to "UPDATE" or to add the hash data */
for (mhold = NULL, i = 0; i < mhash_max; i++) if (mhash[i]) {
if (mhash[i]->pos.ilon == mh->pos.ilon && mhash[i]->pos.ilat == mh->pos.ilat) {
mhold = mhash[i];
break;
}
}
if (mhold != NULL) { /* update !! NOSAVEING !! */
mhash[i] = NULL;
ml_free (mhold);
mhold = NULL;
}
if ((--mhash_pos) < 0) mhash_pos = mhash_max-1;
/* add on the givin place, delete old entry */
mhold = NULL;
if (mhash[mhash_pos]) {
map_hash_free (mhash[mhash_pos], 1);
mhash[mhash_pos] = NULL;
}
/* add or update */
if (mhash[mhash_pos] != NULL) d_printf ("%s:%d map_hash_add: memory leak: not free spot", __FILE__, __LINE__);
mhash[mhash_pos] = mh;
return 1;
};
/******************************************************************************
* remove the hash data from the memory, but in case it has been changed,
* save it. If noremove is set to 1 it won't be checked if we still have the
* pointer inside the hash list.
*/
void map_hash_free (struct map_hash *mh, int noremove) {
int i;
if (ISFLAG(mh->status, MS_changed)) { /* save the hash */
map_save_hash (mh);
}
if (!noremove)
for (i = 0; i < mhash_max; i++) if (mhash[i] == mh) mhash[i] = NULL;
ml_free (mh);
};
/******************************************************************************
* allocate new memory, copy all the data and free the momory again.
*/
struct map_hash *map_hash_realloc (struct map_hash *mhorg, int memsize) {
struct map_hash *res;
int i = memsize;
if (i < mhorg->datasize) i = mhorg->datasize;
res = map_hash_alloc (i);
map_hash_copy (res, mhorg);
/* check if we have to exchange the hash inside the hashtable */
for (i = 0; i < mhash_max; i++) if (mhash[i] == mhorg) mhash[i] = res;
ml_free (mhorg);
return res;
};
/******************************************************************************
* copy data from one to another hash... be sure to reserve enought memory..
* we do no checking. hd (destination) <-- hs (source)
*
*/
void map_hash_copy (struct map_hash *hd, struct map_hash *hs) {
struct map_way *mw;
struct map_area *ma;
struct map_place *mp;
struct map_poi *mpoi;
int i;
/* main informations */
hd->status = hs->status;
hd->pos.ilon = hs->pos.ilon;
hd->pos.ilat = hs->pos.ilat;
hd->wayscnt = 0;
hd->areascnt = 0;
hd->placescnt = 0;
hd->poiscnt = 0;
/* copy way to the hash */
i = 0;
mw = hs->ways;
while (mw && i < hs->wayscnt) {
map_way_add_to_hash (hd, mw);
mw = mw->next;
i++;
}
if (mw) {
d_printf ("%s:%d map_hash_copy all ways copied but: mw != NULL (%p)", __FILE__,__LINE__, mw);
}
/* copy area to the hash */
ma = hs->areas;
i = 0;
while (ma && i < hs->areascnt) {
map_area_add_to_hash (hd, ma);
ma = ma->next;
i++;
}
if (ma) {
d_printf ("%s:%d map_hash_copy all areas copied but: ma != NULL (%p)", __FILE__,__LINE__, ma);
}
/* copy place to the hash */
mp = hs->places;
i = 0;
while (mp && i < hs->placescnt) {
map_place_add_to_hash (hd, mp);
mp = mp->next;
i++;
}
if (mp) {
d_printf ("%s:%d map_hash_copy all places copied but: mp != NULL (%p)", __FILE__, __LINE__, mp);
}
/* copy place to the hash */
mpoi = hs->pois;
i = 0;
while (mpoi && i < hs->poiscnt) {
map_poi_add_to_hash (hd, mpoi);
mpoi = mpoi->next;
i++;
}
if (mpoi) {
d_printf ("%s:%d map_hash_copy all pois copied but: mpoi != NULL (%p) i:%d poiscnt:%d", __FILE__, __LINE__, mpoi, i , hs->poiscnt);
}
};
int map_hash_countways (struct map_hash *mh) {
struct map_way *mw;
int w = 0;
if (mh == NULL) return -1;
for (mw = mh->ways, w = 0; mw; mw = mw->next) w++;
if (mh->wayscnt != w) {
d_printf ("%s:%s map_hash_countways numbers of ways found (%d) is not identical with wayscnt (%d)", __FILE__, __LINE__, w, mh->wayscnt);
mh->wayscnt = w;
}
return w;
};
int map_hash_countareas (struct map_hash *mh) {
struct map_area *ma;
int a = 0;
if (mh == NULL) return -1;
ma = mh->areas;
for (ma = mh->areas, a = 0; ma; ma = ma->next) a++;
return a;
};
/*
* return amount of free space
*/
int map_hash_getfree_size (struct map_hash *mh) {
return (mh->datasize - (mh->free - mh->data));
};
void *map_hash_getfree_aligned (struct map_hash *mh, int align) {
int offset = (long int)mh->free % align;
if (offset !=0) mh->free = mh->free + (align-offset);
return mh->free;
};