Fix:Core:Fix coverity bug #24, Pointer 'table_data' dereferenced before NULL check.
[navit-package] / navit / mapset.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 /** @file
21  * 
22  * @brief Contains code used for loading more than one map
23  *
24  * The code in this file introduces "mapsets", which are collections of several maps.
25  * This enables navit to operate on more than one map at once. See map.c / map.h to learn
26  * how maps are handled.
27  */
28
29 #include <string.h>
30 #include <glib.h>
31 #include <glib/gprintf.h>
32 #include "debug.h"
33 #include "item.h"
34 #include "mapset.h"
35 #include "projection.h"
36 #include "map.h"
37
38 /**
39  * @brief A mapset
40  *
41  * This structure holds a complete mapset
42  */
43 struct mapset {
44         GList *maps; /**< Linked list of all the maps in the mapset */
45 };
46
47 /**
48  * @brief Creates a new, empty mapset
49  *
50  * @return The new mapset 
51  */
52 struct mapset *mapset_new(struct attr *parent, struct attr **attrs)
53 {
54         struct mapset *ms;
55
56         ms=g_new0(struct mapset, 1);
57
58         return ms;
59 }
60
61
62 /**
63  * @brief Adds a map to a mapset
64  *
65  * @param ms The mapset to add the map to
66  * @param m The map to be added
67  */
68 int
69 mapset_add_attr(struct mapset *ms, struct attr *attr)
70 {
71         switch (attr->type) {
72         case attr_map:
73                 ms->maps=g_list_append(ms->maps, attr->u.map);
74                 return 1;
75         default:
76                 return 0;
77         }
78 }
79
80 #if 0
81 static void mapset_maps_free(struct mapset *ms)
82 {
83         /* todo */
84 }
85 #endif
86
87 /**
88  * @brief Destroys a mapset. 
89  *
90  * This destroys a mapset. Please note that it does not touch the contained maps
91  * in any way.
92  *
93  * @param ms The mapset to be destroyed
94  */
95 void mapset_destroy(struct mapset *ms)
96 {
97         g_free(ms);
98 }
99
100 /**
101  * @brief Handle for a mapset in use
102  *
103  * This struct is used for a mapset that is in use. With this it is possible to iterate
104  * all maps in a mapset.
105  */
106 struct mapset_handle {
107         GList *l;       /**< Pointer to the current (next) map */
108 };
109
110 /**
111  * @brief Returns a new handle for a mapset
112  *
113  * This returns a new handle for an existing mapset. The new handle points to the first
114  * map in the set.
115  *
116  * @param ms The mapset to get a handle of
117  * @return The new mapset handle
118  */
119 struct mapset_handle *
120 mapset_open(struct mapset *ms)
121 {
122         struct mapset_handle *ret=NULL;
123         if(ms)
124         {
125                 ret=g_new(struct mapset_handle, 1);
126                 ret->l=ms->maps;
127         }
128
129         return ret;
130 }
131
132 /**
133  * @brief Gets the next map from a mapset handle
134  *
135  * If you set active to true, this function will not return any maps that
136  * have the attr_active attribute associated with them and set to false.
137  *
138  * @param msh The mapset handle to get the next map of
139  * @param active Set to true to only get active maps (See description)
140  * @return The next map
141  */
142 struct map * mapset_next(struct mapset_handle *msh, int active)
143 {
144         struct map *ret;
145         struct attr active_attr;
146
147         for (;;) {
148                 if (!msh || !msh->l)
149                         return NULL;
150                 ret=msh->l->data;
151                 msh->l=g_list_next(msh->l);
152                 if (!active)
153                         return ret;                     
154                 if (!map_get_attr(ret, attr_active, &active_attr, NULL))
155                         return ret;
156                 if (active_attr.u.num)
157                         return ret;
158         }
159 }
160
161 /**
162  * @brief Closes a mapset handle after it is no longer used
163  *
164  * @param msh Mapset handle to be closed
165  */
166 void 
167 mapset_close(struct mapset_handle *msh)
168 {
169         g_free(msh);
170 }
171
172 /**
173  * @brief Holds information about a search in a mapset
174  *
175  * This struct holds information about a search (e.g. for a street) in a mapset. 
176  *
177  * @sa For a more detailed description see the documentation of mapset_search_new().
178  */
179 struct mapset_search {
180         GList *map;                                     /**< The list of maps to be searched within */
181         struct map_search *ms;          /**< A map search struct for the map currently active */
182         struct item *item;                      /**< "Superior" item. */
183         struct attr *search_attr;       /**< Attribute to be searched for. */
184         int partial;                            /**< Indicates if one would like to have partial matches */
185 };
186
187 /**
188  * @brief Starts a search on a mapset
189  *
190  * This function starts a search on a mapset. What attributes one can search for depends on the
191  * map plugin. See the description of map_search_new() in map.c for details.
192  *
193  * If you enable partial matches bear in mind that the search matches only the begin of the
194  * strings - a search for a street named "street" would match to "streetfoo", but not to
195  * "somestreet". Search is case insensitive.
196  *
197  * The item passed to this function specifies a "superior item" to "search within" - e.g. a town 
198  * in which we want to search for a street, or a country in which to search for a town.
199  *
200  * @param ms The mapset that should be searched
201  * @param item Specifies a superior item to "search within" (see description)
202  * @param search_attr Attribute specifying what to search for. See description.
203  * @param partial Set this to true to also have partial matches. See description.
204  * @return A new mapset search struct for this search
205  */
206 struct mapset_search *
207 mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial)
208 {
209         struct mapset_search *this;
210         dbg(1,"enter(%p,%p,%p,%d)\n", ms, item, search_attr, partial);
211         this=g_new0(struct mapset_search,1);
212         if(this != NULL && ms!=NULL )
213         {
214                 this->map=ms->maps;
215                 this->item=item;
216                 this->search_attr=search_attr;
217                 this->partial=partial;
218                 this->ms=map_search_new(this->map->data, item, search_attr, partial);
219                 return this;
220         }
221         else
222         {
223                 return NULL;
224         }
225 }
226
227 /**
228  * @brief Returns the next found item from a mapset search
229  *
230  * This function returns the next item from a mapset search or NULL if there are no more items found.
231  * It automatically iterates through all the maps in the mapset. Please note that maps which have the
232  * attr_active attribute associated with them and set to false are not searched.
233  *
234  * @param this The mapset search to return an item from
235  * @return The next found item or NULL if there are no more items found
236  */
237 struct item *
238 mapset_search_get_item(struct mapset_search *this)
239 {
240         struct item *ret=NULL;
241         struct attr active_attr;
242
243         while ((this) && (!this->ms || !(ret=map_search_get_item(this->ms)))) { /* The current map has no more items to be returned */
244                 if (this->search_attr->type >= attr_country_all && this->search_attr->type <= attr_country_name)
245                         break;
246                 for (;;) {
247                         this->map=g_list_next(this->map);
248                         if (! this->map)
249                                 break;
250                         if (!map_get_attr(this->map->data, attr_active, &active_attr, NULL))
251                                 break;
252                         if (active_attr.u.num)
253                                 break;
254                 }
255                 if (! this->map)
256                         break;
257                 map_search_destroy(this->ms);
258                 this->ms=map_search_new(this->map->data, this->item, this->search_attr, this->partial);
259         }
260         return ret;
261 }
262
263 /**
264  * @brief Destroys a mapset search
265  *
266  * @param this The mapset search to be destroyed
267  */
268 void
269 mapset_search_destroy(struct mapset_search *this)
270 {
271         if (this) {
272                 map_search_destroy(this->ms);
273                 g_free(this);
274         }
275 }