/*************************************************************************** * 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 #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; for (hi = 0; hi < mhash_max; hi++) if (mhash[hi] && mhash[hi]->pos.ilon == ilon && mhash[hi]->pos.ilat == ilat) { res = mhash[hi]; for (; hi > 0; hi--) mhash[hi] = mhash[hi-1]; mhash[0] = res; return res; } if (loadflags & MHLOAD_RELOAD) { if (mhash[mhash_max-1]) { map_hash_free (mhash[mhash_max-1], 1); mhash[mhash_max-1] = NULL; } memmove (&mhash[1], &mhash[0], sizeof (struct map_hash*)*mhash_max-1); mhash[0] = NULL; res = map_load_hash (ilon, ilat); if (res) { mhash[0] = 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, fi = -1; /* fi: free hash position */ 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]; fi = i; break; } } else if (fi == -1) fi = i; } if (mhold != NULL) { /* update !! NOSAVEING !! */ mhash[i] = NULL; ml_free (mhold); mhold = NULL; } /* add on the givin place, delete old entry */ if (fi == -1) { if (mhash[mhash_max-1]) { map_hash_free (mhash[mhash_max-1], 1); mhash[mhash_max-1] = NULL; } memmove (&mhash[0], &mhash[1], sizeof (struct map_hash*)*mhash_max-1); mhash[0] = NULL; mhash[0] = mh; } else mhash[fi] = 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 = NULL; int i = memsize; if (i < mhorg->datasize) return res; 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_append_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_append_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; };