Recreate the navit git/gerrit project that vanished
[profile/ivi/navit.git] / 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 struct attr_iter {
48         GList *last;
49 };
50
51 /**
52  * @brief Creates a new, empty mapset
53  *
54  * @return The new mapset 
55  */
56 struct mapset *mapset_new(struct attr *parent, struct attr **attrs)
57 {
58         struct mapset *ms;
59
60         ms=g_new0(struct mapset, 1);
61
62         return ms;
63 }
64
65
66 struct attr_iter *
67 mapset_attr_iter_new(void)
68 {
69         return g_new0(struct attr_iter, 1);
70 }
71
72 void
73 mapset_attr_iter_destroy(struct attr_iter *iter)
74 {
75         g_free(iter);
76 }
77
78 /**
79  * @brief Adds a map to a mapset
80  *
81  * @param ms The mapset to add the map to
82  * @param m The map to be added
83  */
84 int
85 mapset_add_attr(struct mapset *ms, struct attr *attr)
86 {
87         switch (attr->type) {
88         case attr_map:
89                 ms->maps=g_list_append(ms->maps, attr->u.map);
90                 map_ref(attr->u.map);
91                 return 1;
92         default:
93                 return 0;
94         }
95 }
96
97 int
98 mapset_remove_attr(struct mapset *ms, struct attr *attr)
99 {
100         switch (attr->type) {
101         case attr_map:
102                 ms->maps=g_list_remove(ms->maps, attr->u.map);
103                 return 1;
104         default:
105                 return 0;
106         }
107 }
108
109 int
110 mapset_get_attr(struct mapset *ms, enum attr_type type, struct attr *attr, struct attr_iter *iter)
111 {
112         GList *map;
113         map=ms->maps;
114         attr->type=type;
115         switch (type) {
116         case attr_map:
117                 while (map) {
118                         if (!iter || iter->last == g_list_previous(map)) {
119                                 attr->u.map=map->data;
120                                 if (iter)
121                                         iter->last=map;
122                                 return 1;
123                         }
124                         map=g_list_next(map);
125                 }
126                 break;
127         default:
128                 break;
129         }
130         return 0;
131 }
132
133
134 #if 0
135 static void mapset_maps_free(struct mapset *ms)
136 {
137         /* todo */
138 }
139 #endif
140
141 /**
142  * @brief Destroys a mapset. 
143  *
144  * This destroys a mapset. Please note that it does not touch the contained maps
145  * in any way.
146  *
147  * @param ms The mapset to be destroyed
148  */
149 void mapset_destroy(struct mapset *ms)
150 {
151         GList *map;
152         map=ms->maps;
153         while (map) {
154                 map_destroy(map->data);
155                 map=g_list_next(map);
156         }
157         g_free(ms);
158 }
159
160 /**
161  * @brief Handle for a mapset in use
162  *
163  * This struct is used for a mapset that is in use. With this it is possible to iterate
164  * all maps in a mapset.
165  */
166 struct mapset_handle {
167         GList *l;       /**< Pointer to the current (next) map */
168 };
169
170 /**
171  * @brief Returns a new handle for a mapset
172  *
173  * This returns a new handle for an existing mapset. The new handle points to the first
174  * map in the set.
175  *
176  * @param ms The mapset to get a handle of
177  * @return The new mapset handle
178  */
179 struct mapset_handle *
180 mapset_open(struct mapset *ms)
181 {
182         struct mapset_handle *ret=NULL;
183         if(ms)
184         {
185                 ret=g_new(struct mapset_handle, 1);
186                 ret->l=ms->maps;
187         }
188
189         return ret;
190 }
191
192 /**
193  * @brief Gets the next map from a mapset handle
194  *
195  * If you set active to true, this function will not return any maps that
196  * have the attr_active attribute associated with them and set to false.
197  *
198  * @param msh The mapset handle to get the next map of
199  * @param active Set to true to only get active maps (See description)
200  * @return The next map
201  */
202 struct map * mapset_next(struct mapset_handle *msh, int active)
203 {
204         struct map *ret;
205         struct attr active_attr;
206
207         for (;;) {
208                 if (!msh || !msh->l)
209                         return NULL;
210                 ret=msh->l->data;
211                 msh->l=g_list_next(msh->l);
212                 if (!active)
213                         return ret;                     
214                 if (active == 2 && map_get_attr(ret, attr_route_active, &active_attr, NULL)) {
215                         if (active_attr.u.num)
216                                 return ret;
217                         else
218                                 continue;
219                 }
220                 if (active == 3 && map_get_attr(ret, attr_search_active, &active_attr, NULL)) {
221                         if (active_attr.u.num)
222                                 return ret;
223                         else
224                                 continue;
225                 }
226                 if (!map_get_attr(ret, attr_active, &active_attr, NULL))
227                         return ret;
228                 if (active_attr.u.num)
229                         return ret;
230         }
231 }
232
233 /**
234  * @brief Gets a map from the mapset by name
235  *
236  * @param ms The map
237  * @param map_name the map name used by the search
238  * @return The next map
239  */
240 struct map * 
241 mapset_get_map_by_name(struct mapset *ms, char*map_name)
242 {
243         struct mapset_handle*msh;
244         struct map*curr_map;
245         struct attr map_attr;
246         if( !ms || !map_name ) {
247                 return NULL;
248         }
249         msh=mapset_open(ms);
250         while ((curr_map=mapset_next(msh, 1))) {
251                 //get map name
252                 if(map_get_attr(curr_map,attr_name, &map_attr,NULL)) {
253                         if( ! strcmp(map_attr.u.str, map_name)) {
254                                 break;
255                         }
256                 }
257         }
258         return curr_map;
259 }
260
261 /**
262  * @brief Closes a mapset handle after it is no longer used
263  *
264  * @param msh Mapset handle to be closed
265  */
266 void 
267 mapset_close(struct mapset_handle *msh)
268 {
269         g_free(msh);
270 }
271
272 /**
273  * @brief Holds information about a search in a mapset
274  *
275  * This struct holds information about a search (e.g. for a street) in a mapset. 
276  *
277  * @sa For a more detailed description see the documentation of mapset_search_new().
278  */
279 struct mapset_search {
280         GList *map;                                     /**< The list of maps to be searched within */
281         struct map_search *ms;          /**< A map search struct for the map currently active */
282         struct item *item;                      /**< "Superior" item. */
283         struct attr *search_attr;       /**< Attribute to be searched for. */
284         int partial;                            /**< Indicates if one would like to have partial matches */
285 };
286
287 /**
288  * @brief Starts a search on a mapset
289  *
290  * This function starts a search on a mapset. What attributes one can search for depends on the
291  * map plugin. See the description of map_search_new() in map.c for details.
292  *
293  * If you enable partial matches bear in mind that the search matches only the begin of the
294  * strings - a search for a street named "street" would match to "streetfoo", but not to
295  * "somestreet". Search is case insensitive.
296  *
297  * The item passed to this function specifies a "superior item" to "search within" - e.g. a town 
298  * in which we want to search for a street, or a country in which to search for a town.
299  *
300  * @param ms The mapset that should be searched
301  * @param item Specifies a superior item to "search within" (see description)
302  * @param search_attr Attribute specifying what to search for. See description.
303  * @param partial Set this to true to also have partial matches. See description.
304  * @return A new mapset search struct for this search
305  */
306 struct mapset_search *
307 mapset_search_new(struct mapset *ms, struct item *item, struct attr *search_attr, int partial)
308 {
309         struct mapset_search *this;
310         dbg(1,"enter(%p,%p,%p,%d)\n", ms, item, search_attr, partial);
311         this=g_new0(struct mapset_search,1);
312         if(this != NULL && ms!=NULL )
313         {
314                 this->map=ms->maps;
315                 this->item=item;
316                 this->search_attr=search_attr;
317                 this->partial=partial;
318                 this->ms=map_search_new(this->map->data, item, search_attr, partial);
319                 return this;
320         }
321         else
322         {
323                 return NULL;
324         }
325 }
326
327 /**
328  * @brief Returns the next found item from a mapset search
329  *
330  * This function returns the next item from a mapset search or NULL if there are no more items found.
331  * It automatically iterates through all the maps in the mapset. Please note that maps which have the
332  * attr_active attribute associated with them and set to false are not searched.
333  *
334  * @param this The mapset search to return an item from
335  * @return The next found item or NULL if there are no more items found
336  */
337 struct item *
338 mapset_search_get_item(struct mapset_search *this_)
339 {
340         struct item *ret=NULL;
341         struct attr active_attr;
342
343         while ((this_) && (!this_->ms || !(ret=map_search_get_item(this_->ms)))) { /* The current map has no more items to be returned */
344                 if (this_->search_attr->type >= attr_country_all && this_->search_attr->type <= attr_country_name)
345                         break;
346                 for (;;) {
347                         this_->map=g_list_next(this_->map);
348                         if (! this_->map)
349                                 break;
350                         if (map_get_attr(this_->map->data, attr_search_active, &active_attr, NULL)) {
351                                 if (!active_attr.u.num)
352                                         continue;
353                         }
354                         if (!map_get_attr(this_->map->data, attr_active, &active_attr, NULL))
355                                 break;
356                         if (active_attr.u.num)
357                                 break;
358                 }
359                 if (! this_->map)
360                         break;
361                 map_search_destroy(this_->ms);
362                 this_->ms=map_search_new(this_->map->data, this_->item, this_->search_attr, this_->partial);
363         }
364         return ret;
365 }
366
367 /**
368  * @brief Destroys a mapset search
369  *
370  * @param this The mapset search to be destroyed
371  */
372 void
373 mapset_search_destroy(struct mapset_search *this_)
374 {
375         if (this_) {
376                 map_search_destroy(this_->ms);
377                 g_free(this_);
378         }
379 }