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.
306 lines
7.9 KiB
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;
|
|
};
|