Fix a crash
[framework/location/libdecarta.git] / decarta / decarta_types.c
1 /*
2  * libdecarta
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <glib.h>
27 #include <decarta_types.h>
28
29 EXPORT_API DecartaPosition *
30 decarta_position_new (double latitude,
31         double longitude)
32 {
33         DecartaPosition *pos = g_new0 (DecartaPosition, 1);
34         pos->latitude = latitude;
35         pos->longitude = longitude;
36         return pos;
37 }
38
39 EXPORT_API DecartaPosition *
40 decarta_position_copy (const DecartaPosition *pos)
41 {
42         g_return_val_if_fail (pos, NULL);
43         return decarta_position_new (pos->latitude, pos->longitude);
44 }
45
46 EXPORT_API void
47 decarta_position_free (DecartaPosition *pos)
48 {
49         g_return_if_fail (pos);
50         g_free (pos);
51 }
52
53 static void
54 _position_list_free_gfunc (gpointer data,
55         gpointer user_data)
56 {
57         DecartaPosition* pos = (DecartaPosition*)data;
58         decarta_position_free (pos);
59 }
60
61 EXPORT_API GList*
62 decarta_position_list_append (GList *pos_list, DecartaPosition *pos)
63 {
64         g_return_val_if_fail (pos, NULL);
65         return g_list_append (pos_list, (gpointer)pos);
66 }
67
68 EXPORT_API void
69 decarta_position_list_free (GList *pos_list)
70 {
71         g_return_if_fail (pos_list);
72         g_list_foreach(pos_list, (GFunc)_position_list_free_gfunc, NULL);
73         g_list_free (pos_list);
74 }
75
76 EXPORT_API GList *
77 decarta_position_list_next (const GList *pos_list,
78         const DecartaPosition ** pos)
79 {
80         g_return_val_if_fail (pos_list, NULL);
81         g_return_val_if_fail (pos, NULL);
82         *pos = (DecartaPosition*)pos_list->data;
83         return g_list_next (pos_list);
84 }
85
86 EXPORT_API GList *
87 decarta_position_list_copy (const GList *pos_list)
88 {
89         g_return_val_if_fail (pos_list, NULL);
90         GList *dup_pos_list = NULL;
91         const DecartaPosition *pos = NULL;
92         pos_list = decarta_position_list_next(pos_list, &pos);
93         while (pos) {
94                 dup_pos_list = decarta_position_list_append (dup_pos_list, decarta_position_copy (pos));
95                 if (!pos_list) break;
96                 pos_list = decarta_position_list_next(pos_list, &pos);
97         }
98         return dup_pos_list;
99 }
100
101 EXPORT_API DecartaFormedAddress *
102 decarta_formed_address_new (const char *street_number,
103         const char *street_name,
104         const char *state,
105         const char *county,
106         const char *city,
107         const char *district,
108         const char* postal_code,
109         const char* landmark_type,
110         const char* landmark_name)
111 {
112         DecartaFormedAddress *formed_addr = g_new0 (DecartaFormedAddress, 1 );
113         formed_addr->street_number = g_strdup (street_number);
114         formed_addr->street_name = g_strdup (street_name);
115         formed_addr->state = g_strdup (state);
116         formed_addr->county = g_strdup (county);
117         formed_addr->city = g_strdup (city);
118         formed_addr->district = g_strdup (district);
119         formed_addr->postal_code = g_strdup (postal_code);
120         formed_addr->landmark_type = g_strdup (landmark_type);
121         formed_addr->landmark_name = g_strdup (landmark_name);
122         return formed_addr;
123 }
124
125 EXPORT_API void
126 decarta_formed_address_free (DecartaFormedAddress *formed_addr)
127 {
128         g_return_if_fail (formed_addr);
129         g_free(formed_addr->street_number);
130         g_free(formed_addr->street_name);
131         g_free(formed_addr->state);
132         g_free(formed_addr->county);
133         g_free(formed_addr->city );
134         g_free(formed_addr->district);
135         g_free(formed_addr->postal_code);
136         g_free(formed_addr->landmark_type);
137         g_free(formed_addr->landmark_name);
138         g_free(formed_addr);
139 }
140
141 EXPORT_API DecartaFormedAddress *
142 decarta_formed_address_copy (const DecartaFormedAddress *formed_addr)
143 {
144         g_return_val_if_fail (formed_addr, NULL);
145         return decarta_formed_address_new (formed_addr->street_number, formed_addr->street_name, formed_addr->state, formed_addr->county, formed_addr->city, formed_addr->district, formed_addr->postal_code, formed_addr->landmark_type, formed_addr->landmark_name);
146 }
147
148 EXPORT_API DecartaAddress *
149 decarta_address_new (const char* country_code,
150         const char *language_code,
151         gboolean is_freerorm,
152         const char *freeform_address,
153         const DecartaFormedAddress *formed_addr)
154 {
155         DecartaAddress *addr = g_new0 (DecartaAddress, 1 );
156         addr->country_code = g_strdup (country_code);
157         addr->language_code = g_strdup (language_code);
158         addr->is_freerorm = is_freerorm;
159         if (addr->is_freerorm) addr->freeform_address = g_strdup (freeform_address);
160         else addr->formed_addr = decarta_formed_address_copy (formed_addr);
161         return addr;
162 }
163
164 EXPORT_API void
165 decarta_address_free (DecartaAddress *addr)
166 {
167         g_return_if_fail (addr);
168         g_free(addr->country_code);
169         g_free(addr->language_code);
170         if (addr->is_freerorm) g_free (addr->freeform_address);
171         else                   decarta_formed_address_free (addr->formed_addr);
172         g_free (addr);
173 }
174
175 EXPORT_API DecartaBoundary *
176 decarta_boundary_new_for_rect (DecartaPosition* left_top,
177         DecartaPosition* right_bottom)
178 {
179         g_return_val_if_fail(left_top, NULL);
180         g_return_val_if_fail(right_bottom, NULL);
181
182         gdouble lon_interval = right_bottom->longitude - left_top->longitude;
183
184         if(lon_interval < 180 && lon_interval > -180) {
185                 if(right_bottom->longitude <= left_top->longitude || right_bottom->latitude >= left_top->latitude)
186                         return NULL;
187         }
188         else {
189                 if(right_bottom->longitude >= left_top->longitude || right_bottom->latitude >= left_top->latitude)
190                         return NULL;
191         }
192
193         DecartaBoundary* boundary = g_slice_new0 (DecartaBoundary);
194         boundary->type = DECARTA_BOUNDARY_RECT;
195         boundary->rect.left_top = decarta_position_copy(left_top);
196         boundary->rect.right_bottom = decarta_position_copy(right_bottom);
197         return boundary;
198 }
199
200 EXPORT_API DecartaBoundary *
201 decarta_boundary_new_for_circle (DecartaPosition* center,
202         gdouble radius)
203 {
204         g_return_val_if_fail(center, NULL);
205         g_return_val_if_fail(radius > 0, NULL);
206         DecartaBoundary* boundary = g_slice_new0 (DecartaBoundary);
207         boundary->type = DECARTA_BOUNDARY_CIRCLE;
208         boundary->circle.center = decarta_position_copy(center);
209         boundary->circle.radius = radius;
210         return boundary;
211 }
212
213 static void __decarta_append_polygon_position(gpointer data, gpointer user_data)
214 {
215         g_return_if_fail(data);
216         g_return_if_fail(user_data);
217
218         DecartaBoundary* boundary = (DecartaBoundary*)user_data;
219         DecartaPosition* position = (DecartaPosition *)data;
220         DecartaPosition* new_position = decarta_position_copy(position);
221
222         boundary->polygon.position_list = g_list_append(boundary->polygon.position_list, new_position);
223 }
224
225
226 EXPORT_API DecartaBoundary *
227 decarta_boundary_new_for_polygon(GList *position_list)
228 {
229         g_return_val_if_fail(position_list, NULL);
230         g_return_val_if_fail(g_list_length(position_list) > 2, NULL);
231
232         DecartaBoundary *boundary = g_slice_new0 (DecartaBoundary);
233
234         g_list_foreach(position_list, (GFunc)__decarta_append_polygon_position, boundary);
235         boundary->type = DECARTA_BOUNDARY_POLYGON;
236         boundary->polygon.position_list = g_list_first(boundary->polygon.position_list);
237
238         return boundary;
239 }
240
241 static void __decarta_free_polygon_position(gpointer data)
242 {
243         g_return_if_fail(data);
244
245         DecartaPosition* position = (DecartaPosition *)data;
246         decarta_position_free(position);
247 }
248
249 EXPORT_API void
250 decarta_boundary_free (DecartaBoundary* boundary)
251 {
252         g_return_if_fail(boundary);
253
254         if (boundary->type == DECARTA_BOUNDARY_RECT) {
255                 decarta_position_free(boundary->rect.left_top);
256                 decarta_position_free(boundary->rect.right_bottom);
257         } else if (boundary->type == DECARTA_BOUNDARY_CIRCLE) {
258                 decarta_position_free(boundary->circle.center);
259         } else if (boundary->type == DECARTA_BOUNDARY_POLYGON) {
260                 g_list_free_full(boundary->polygon.position_list, (GDestroyNotify)__decarta_free_polygon_position);
261         }
262         g_slice_free(DecartaBoundary, boundary);
263 }
264
265 EXPORT_API DecartaBoundary*
266 decarta_boundary_copy (const DecartaBoundary* boundary)
267 {
268         g_return_val_if_fail(boundary, NULL);
269         if (boundary->type == DECARTA_BOUNDARY_RECT) {
270                 return decarta_boundary_new_for_rect(boundary->rect.left_top, boundary->rect.right_bottom);
271         } else if (boundary->type == DECARTA_BOUNDARY_CIRCLE) {
272                 return decarta_boundary_new_for_circle(boundary->circle.center, boundary->circle.radius);
273         } else if (boundary->type == DECARTA_BOUNDARY_POLYGON) {
274                 return decarta_boundary_new_for_polygon(boundary->polygon.position_list);
275         }
276         return NULL;
277 }
278
279 EXPORT_API gboolean
280 decarta_boundary_if_inside (DecartaBoundary* boundary,
281         const DecartaPosition* position)
282 {
283         g_return_val_if_fail(boundary, FALSE);
284         g_return_val_if_fail(position, FALSE);
285
286         gboolean is_inside = FALSE;
287
288         switch(boundary->type) {
289
290                 case DECARTA_BOUNDARY_RECT: {
291                         gdouble y = position->latitude;
292                         gdouble x = position->longitude;
293
294                         gdouble lt_y = boundary->rect.left_top->latitude;
295                         gdouble lt_x = boundary->rect.left_top->longitude;
296                         gdouble rb_y = boundary->rect.right_bottom->latitude;
297                         gdouble rb_x = boundary->rect.right_bottom->longitude;
298
299                         if (lt_x - rb_x < 180 && lt_x - rb_x > -180) {
300                                 if ((rb_y < y && y < lt_y) && ( lt_x < x && x < rb_x)) {
301                                         is_inside = TRUE;
302                                 }
303                         }
304                         else {
305                                 if ((rb_y < y && y < lt_y) && ( lt_x < x || x < rb_x)) {
306                                         is_inside = TRUE;
307                                 }
308                         }
309                         break;
310                 }
311                 case DECARTA_BOUNDARY_CIRCLE: {
312                         break;
313                 }
314                 case DECARTA_BOUNDARY_POLYGON: {
315                         break;
316                 }
317                 default: {
318                         break;
319                 }
320         }
321
322         return is_inside;
323 }
324
325
326 EXPORT_API DecartaAddress *
327 decarta_addr_copy (const DecartaAddress *addr)
328 {
329         g_return_val_if_fail(addr, NULL);
330         return decarta_address_new (addr->country_code, addr->language_code, addr->is_freerorm, addr->freeform_address, addr->formed_addr);
331 }
332
333 EXPORT_API DecartaPOI *
334 decarta_poi_new (const char *name,
335         const char* id,
336         const char* phone_number,
337         const DecartaPOIInfoTable* info_list,
338         const DecartaPosition *pos,
339         const DecartaAddress *addr,
340         double distance)
341 {
342         DecartaPOI *poi = g_new0 (DecartaPOI, 1 );
343         poi->name = g_strdup (name);
344         poi->id = g_strdup (id);
345         poi->phone_number = g_strdup (phone_number);
346         poi->info_list = decarta_poi_info_table_copy (info_list);
347         poi->pos = decarta_position_copy (pos);
348         poi->addr = decarta_addr_copy (addr);
349         poi->distance = distance;
350         return poi;
351 }
352
353 EXPORT_API void
354 decarta_poi_free (DecartaPOI *poi)
355 {
356         g_return_if_fail (poi);
357         g_free (poi->name);
358         g_free (poi->id);
359         g_free (poi->phone_number);
360         decarta_poi_info_table_free (poi->info_list);
361         decarta_address_free (poi->addr);
362         g_free (poi);
363 }
364
365 EXPORT_API DecartaPOI *
366 decarta_poi_copy (const DecartaPOI *poi)
367 {
368         g_return_val_if_fail(poi, NULL);
369         return decarta_poi_new (poi->name, poi->id, poi->phone_number, poi->info_list, poi->pos, poi->addr, poi->distance);
370 }
371
372 static void
373 _poi_list_free_gfunc (gpointer data,
374         gpointer user_data)
375 {
376         DecartaPOI* poi = (DecartaPOI*)data;
377         decarta_poi_free (poi);
378 }
379
380 EXPORT_API GList*
381 decarta_poi_list_append (GList *poi_list, DecartaPOI *poi)
382 {
383         g_return_val_if_fail (poi, NULL);
384         return g_list_append (poi_list, (gpointer)poi);
385 }
386
387 EXPORT_API void decarta_poi_list_free (GList *poi_list)
388 {
389         g_return_if_fail (poi_list);
390         g_list_foreach(poi_list, (GFunc)_poi_list_free_gfunc, NULL);
391         g_list_free (poi_list);
392 }
393
394 EXPORT_API GList *
395 decarta_poi_list_next (const GList *poi_list,
396         const DecartaPOI** poi)
397 {
398         g_return_val_if_fail (poi_list, NULL);
399         g_return_val_if_fail (poi, NULL);
400         *poi = (DecartaPOI*)poi_list->data;
401         return g_list_next (poi_list);
402 }
403
404 EXPORT_API GList *
405 decarta_poi_list_copy (const GList *poi_list)
406 {
407         g_return_val_if_fail (poi_list, NULL);
408         GList *dup_poi_list = NULL;
409         const DecartaPOI *poi = NULL;
410         poi_list = decarta_poi_list_next(poi_list, &poi);
411         while (poi) {
412                 dup_poi_list = g_list_append (dup_poi_list, decarta_poi_copy (poi));
413                 if (!poi_list) break;
414                 poi_list = decarta_poi_list_next(poi_list, &poi);
415         }
416         return dup_poi_list;
417 }
418
419 EXPORT_API DecartaPOIInfoTable *
420 decarta_poi_info_table_new (void)
421 {
422         DecartaPOIInfoTable *info_list = g_new0 (DecartaPOIInfoTable, 1);
423         info_list->table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
424         return info_list;
425 }
426
427 EXPORT_API void
428 decarta_poi_info_table_free (DecartaPOIInfoTable* poi_info_list)
429 {
430         g_return_if_fail(poi_info_list);
431         g_return_if_fail(poi_info_list->table);
432         g_hash_table_destroy(poi_info_list->table);
433         g_free (poi_info_list);
434 }
435
436 EXPORT_API gboolean
437 decarta_poi_info_table_insert (DecartaPOIInfoTable* poi_info_list,
438         const gchar* name,
439         const gchar* value)
440 {
441         g_return_val_if_fail(poi_info_list, FALSE);
442         g_return_val_if_fail(poi_info_list->table, FALSE);
443         g_hash_table_insert (poi_info_list->table, g_strdup(name), g_strdup(value));
444         return TRUE;
445 }
446
447 EXPORT_API gboolean
448 decarta_poi_info_table_iter_init (DecartaPOIInfoTable* poi_info_list)
449 {
450         g_return_val_if_fail(poi_info_list, FALSE);
451         g_return_val_if_fail(poi_info_list->table, FALSE);
452         g_hash_table_iter_init (&poi_info_list->iter, poi_info_list->table);
453         return TRUE;
454 }
455
456 EXPORT_API gboolean
457 decarta_poi_info_list_table_next (DecartaPOIInfoTable* poi_info_list,
458         gchar** name,
459         gchar** value)
460 {
461         g_return_val_if_fail(poi_info_list, FALSE);
462         g_return_val_if_fail(poi_info_list->table, FALSE);
463         return g_hash_table_iter_next (&poi_info_list->iter, (gpointer*)name, (gpointer*)value);
464 }
465
466 static void
467 copy_poi_info_table_func (gchar *key,
468         gchar *value,
469         DecartaPOIInfoTable *dup)
470 {
471         g_return_if_fail (dup);
472         decarta_poi_info_table_insert(dup, key, value);
473 }
474
475 EXPORT_API DecartaPOIInfoTable *
476 decarta_poi_info_table_copy (const DecartaPOIInfoTable *poi_info_list)
477 {
478         g_return_val_if_fail(poi_info_list, NULL);
479         DecartaPOIInfoTable *dup = decarta_poi_info_table_new ();
480         g_hash_table_foreach (poi_info_list->table,
481                               (GHFunc)copy_poi_info_table_func,
482                               dup);
483         return dup;
484 }
485
486 EXPORT_API DecartaPOIProperty *
487 decarta_poi_property_new (const char* poi_name,
488         const char* keyword,
489         const char* brand,
490         const char* type,
491         const char* description,
492         const char* URL)
493 {
494         DecartaPOIProperty *property = g_new0 (DecartaPOIProperty, 1 );
495         property->poi_name = g_strdup(poi_name);
496         property->keyword = g_strdup(keyword);
497         property->brand = g_strdup(brand);
498         property->type = g_strdup(type);
499         property->description = g_strdup(description);
500         property->URL = g_strdup(URL);
501         return property;
502 }
503
504 EXPORT_API void
505 decarta_poi_property_free (DecartaPOIProperty *property)
506 {
507         g_return_if_fail (property);
508         g_free (property->poi_name);
509         g_free (property->keyword);
510         g_free (property->brand);
511         g_free (property->type);
512         g_free (property->description);
513         g_free (property->URL);
514         g_free (property);
515 }
516
517 EXPORT_API DecartaPOIProperty *
518 decarta_poi_property_copy (const DecartaPOIProperty *property)
519 {
520         g_return_val_if_fail(property, NULL);
521         return decarta_poi_property_new (property->poi_name, property->keyword, property->brand, property->type, property->description, property->URL);
522 }
523
524
525 EXPORT_API DecartaPOIPreference *
526 decarta_poi_preference_new (guint max_result_cnt,
527         DecartaPOIPrefSortOrder sort_order,
528         const gchar *item)
529 {
530         DecartaPOIPreference *pref = g_new0 (DecartaPOIPreference, 1 );
531         pref->max_result_cnt = max_result_cnt;
532         pref->sort_order = sort_order;
533         pref->item = g_strdup(item);
534         return pref;
535 }
536
537 EXPORT_API void
538 decarta_poi_preference_free (DecartaPOIPreference *preference)
539 {
540         g_return_if_fail (preference);
541         g_free (preference->item);
542         g_free (preference);
543 }
544
545 EXPORT_API DecartaPOIPreference *
546 decarta_poi_preference_copy (const DecartaPOIPreference *preference)
547 {
548         g_return_val_if_fail(preference, NULL);
549         //When decarta_directory_request_new() was call without item, it reaturns fail.
550         //g_return_val_if_fail(preference->item, NULL);
551         return decarta_poi_preference_new(preference->max_result_cnt, preference->sort_order, preference->item);
552 }
553
554 EXPORT_API DecartaGeocode *
555 decarta_geocode_new (const DecartaPosition *pos,
556         const DecartaAddress *addr)
557 {
558         DecartaGeocode *geocode = g_new0 (DecartaGeocode, 1);
559         if (pos) geocode->pos = decarta_position_copy (pos);
560         if (addr) geocode->addr = decarta_addr_copy (addr);
561         return geocode;
562 }
563
564 EXPORT_API DecartaGeocode *
565 decarta_geocode_copy (const DecartaGeocode *geocode)
566 {
567         g_return_val_if_fail (geocode, NULL);
568         return decarta_geocode_new (geocode->pos, geocode->addr);
569 }
570
571 EXPORT_API void
572 decarta_geocode_free (DecartaGeocode *geocode)
573 {
574         g_return_if_fail (geocode);
575         if (geocode->pos)  decarta_position_free (geocode->pos);
576         if (geocode->addr) decarta_address_free (geocode->addr);
577         g_free (geocode);
578 }
579
580 static void
581 _geocode_list_free_gfunc (gpointer data,
582         gpointer user_data)
583 {
584         DecartaGeocode* geocode = (DecartaGeocode*)data;
585         decarta_geocode_free (geocode);
586 }
587
588 EXPORT_API GList*
589 decarta_geocode_list_append (GList *geocode_list, DecartaGeocode *geocode)
590 {
591         g_return_val_if_fail (geocode, NULL);
592         return g_list_append (geocode_list, (gpointer)geocode);
593 }
594
595 EXPORT_API
596 void decarta_geocode_list_free (GList *geocode_list)
597 {
598         g_return_if_fail (geocode_list);
599         g_list_foreach(geocode_list, (GFunc)_geocode_list_free_gfunc, NULL);
600         g_list_free (geocode_list);
601 }
602
603 EXPORT_API GList *
604 decarta_geocode_list_next (const GList *geocode_list,
605         const DecartaGeocode **geocode)
606 {
607         g_return_val_if_fail (geocode_list, NULL);
608         g_return_val_if_fail (geocode, NULL);
609         *geocode = (DecartaGeocode*)geocode_list->data;
610         return g_list_next (geocode_list);
611 }
612
613 EXPORT_API GList *
614 decarta_geocode_list_copy (const GList *geocode_list)
615 {
616         g_return_val_if_fail (geocode_list, NULL);
617         GList *dup_geocode_list = NULL;
618         const DecartaGeocode *geocode = NULL;
619         geocode_list = decarta_geocode_list_next(geocode_list, &geocode);
620         while (geocode) {
621                 dup_geocode_list = g_list_append (dup_geocode_list, decarta_geocode_copy (geocode));
622                 if (!geocode_list) break;
623                 geocode_list = decarta_geocode_list_next(geocode_list, &geocode);
624         }
625         return dup_geocode_list;
626 }
627
628 EXPORT_API DecartaMap *
629 decarta_map_new (const DecartaPosition *center,
630         const DecartaPosition *box_corner1,
631         const DecartaPosition *box_corner2,
632         const char *tile_url,
633         double radius)
634 {
635         DecartaMap *map = g_new0 (DecartaMap, 1);
636         if (center) map->center = decarta_position_copy (center);
637         if (box_corner1) map->box_corner1 = decarta_position_copy (box_corner1);
638         if (box_corner2) map->box_corner2 = decarta_position_copy (box_corner2);
639         if (tile_url) map->tile_url = g_strdup (tile_url);
640         map->radius = radius;
641         return map ;
642 }
643
644 EXPORT_API DecartaMap *
645 decarta_map_copy (const DecartaMap *map)
646 {
647         g_return_val_if_fail (map, NULL);
648         return decarta_map_new (map->center, map->box_corner1, map->box_corner2,  map->tile_url, map->radius);
649 }
650
651 EXPORT_API void
652 decarta_map_free (DecartaMap *map)
653 {
654         g_return_if_fail (map);
655         if (map->center)  decarta_position_free (map->center);
656         if (map->box_corner1)  decarta_position_free (map->box_corner1);
657         if (map->box_corner2)  decarta_position_free (map->box_corner2);
658         if (map->tile_url) g_free (map->tile_url);
659         g_free (map);
660 }
661
662 static void
663 _map_list_free_gfunc (gpointer data,
664         gpointer user_data)
665 {
666         DecartaMap* map = (DecartaMap*)data;
667         decarta_map_free (map);
668 }
669
670 EXPORT_API GList*
671 decarta_map_list_append (GList *map_list, DecartaMap *map)
672 {
673         g_return_val_if_fail (map, NULL);
674         return g_list_append (map_list, (gpointer)map);
675 }
676
677 EXPORT_API void
678 decarta_map_list_free (GList *map_list)
679 {
680         g_return_if_fail (map_list);
681         g_list_foreach(map_list, (GFunc)_map_list_free_gfunc, NULL);
682         g_list_free (map_list);
683 }
684
685 EXPORT_API GList *
686 decarta_map_list_next (const GList *map_list,
687         const DecartaMap** map)
688 {
689         g_return_val_if_fail (map_list, NULL);
690         g_return_val_if_fail (map, NULL);
691         *map = (DecartaMap*)map_list->data;
692         return g_list_next (map_list);
693 }
694
695 EXPORT_API GList *
696 decarta_map_list_copy (const GList *map_list)
697 {
698         g_return_val_if_fail (map_list, NULL);
699         GList *dup_map_list = NULL;
700         const DecartaMap *map = NULL;
701         map_list = decarta_map_list_next(map_list, &map);
702         while (map) {
703                 dup_map_list = g_list_append (dup_map_list, decarta_map_copy (map));
704                 if (!map_list) break;
705                 map_list = decarta_map_list_next(map_list, &map);
706         }
707         return dup_map_list;
708 }
709
710 EXPORT_API DecartaRoute *
711 decarta_route_new (const GList *start_geo_list, const GList *end_geo_list,
712         unsigned int total_time,
713         double total_distance,
714         const DecartaPosition *box_corner1, const DecartaPosition *box_corner2,
715         const DecartaMap *overview,
716         const GList *line_pos_list,
717         const GList *instructions_list)
718 {
719         DecartaRoute *route = g_new0 (DecartaRoute, 1);
720         if (start_geo_list) route->start_geo_list = decarta_geocode_list_copy (start_geo_list);
721         if (end_geo_list) route->end_geo_list = decarta_geocode_list_copy (end_geo_list);
722         route->total_time = total_time;
723         route->total_distance = total_distance;
724         if (box_corner1) route->box_corner1 = decarta_position_copy (box_corner1);
725         if (box_corner2) route->box_corner2 = decarta_position_copy (box_corner2);
726         if (overview) route->overview = decarta_map_copy (overview);
727         if (line_pos_list) route->line_pos_list = decarta_position_list_copy (line_pos_list);
728         if (instructions_list) route->instructions_list = decarta_route_instructions_list_copy (instructions_list);
729         return route;
730 }
731
732 EXPORT_API DecartaRoute *
733 decarta_route_copy (const DecartaRoute *route)
734 {
735         g_return_val_if_fail (route, NULL);
736         return decarta_route_new (route->start_geo_list, route->end_geo_list,
737                         route->total_time, route->total_distance,
738                         route->box_corner1, route->box_corner2, route->overview,
739                         route->line_pos_list, route->instructions_list);
740 }
741
742 EXPORT_API void
743 decarta_route_free (DecartaRoute *route)
744 {
745         g_return_if_fail (route);
746         if (route->start_geo_list) decarta_geocode_list_free (route->start_geo_list);
747         if (route->end_geo_list) decarta_geocode_list_free (route->end_geo_list);
748         if (route->box_corner1) decarta_position_free (route->box_corner1);
749         if (route->box_corner2) decarta_position_free (route->box_corner2);
750         if (route->line_pos_list) decarta_position_list_free (route->line_pos_list);
751         if (route->overview) decarta_map_free (route->overview);
752         if (route->instructions_list) decarta_route_instructions_list_free (route->instructions_list);
753         g_free (route);
754 }
755
756
757 EXPORT_API DecartaRouteInstructions*
758 decarta_route_instructions_new (const char *tour,
759         unsigned int duration,
760         double distance,
761         const char *instruction,
762         const DecartaMap *map)
763 {
764         DecartaRouteInstructions *route_inst = g_new0 (DecartaRouteInstructions, 1);
765         if (tour) route_inst->tour = g_strdup (tour);
766         route_inst->duration = duration;
767         route_inst->distance = distance;
768         if (instruction) route_inst->instruction = g_strdup (instruction);
769         if (map) route_inst->map = decarta_map_copy (map);
770         return route_inst;
771 }
772
773 EXPORT_API DecartaRouteInstructions *
774 decarta_route_instructions_copy (const DecartaRouteInstructions *route_inst)
775 {
776         g_return_val_if_fail (route_inst, NULL);
777         return decarta_route_instructions_new (route_inst->tour, route_inst->duration,
778                         route_inst->distance, route_inst->instruction, route_inst->map);
779 }
780
781 EXPORT_API void
782 decarta_route_instructions_free (DecartaRouteInstructions *route_inst)
783 {
784         g_return_if_fail (route_inst);
785         g_free (route_inst->tour);
786         g_free (route_inst->instruction);
787         decarta_map_free (route_inst->map);
788         g_free (route_inst);
789 }
790
791 static void
792 _route_instructions_list_free_gfunc (gpointer data,
793         gpointer user_data)
794 {
795         DecartaRouteInstructions* route_inst = (DecartaRouteInstructions*)data;
796         decarta_route_instructions_free (route_inst);
797 }
798
799 EXPORT_API GList*
800 decarta_route_instructions_list_append (GList *route_inst_list, DecartaRouteInstructions *route_inst)
801 {
802         g_return_val_if_fail (route_inst, NULL);
803         return g_list_append (route_inst_list, (gpointer)route_inst);
804 }
805
806 EXPORT_API void
807 decarta_route_instructions_list_free (GList *route_inst_list)
808 {
809         g_return_if_fail (route_inst_list);
810         g_list_foreach(route_inst_list, (GFunc)_route_instructions_list_free_gfunc, NULL);
811         g_list_free (route_inst_list);
812 }
813
814 EXPORT_API GList *
815 decarta_route_instructions_list_next (const GList *route_inst_list,
816         const DecartaRouteInstructions** route_inst)
817 {
818         g_return_val_if_fail (route_inst_list, NULL);
819         g_return_val_if_fail (route_inst, NULL);
820         *route_inst = (DecartaRouteInstructions*)route_inst_list->data;
821         return g_list_next (route_inst_list);
822 }
823
824 EXPORT_API GList *
825 decarta_route_instructions_list_copy (const GList *route_inst_list)
826 {
827         g_return_val_if_fail (route_inst_list, NULL);
828         GList *dup_route_inst_list = NULL;
829         const DecartaRouteInstructions *route_inst = NULL;
830         route_inst_list = decarta_route_instructions_list_next(route_inst_list, &route_inst);
831         while (route_inst) {
832                 dup_route_inst_list = g_list_append (dup_route_inst_list, decarta_route_instructions_copy (route_inst));
833                 if (!route_inst_list) break;
834                 route_inst_list = decarta_route_instructions_list_next(route_inst_list, &route_inst);
835         }
836         return dup_route_inst_list;
837 }
838
839 EXPORT_API DecartaDirectoryRequest *
840 decarta_directory_request_new (const DecartaPOIPreference *pref,
841         DecartaDirectorySearchType search_type,
842         DecartaDirectoryType type,
843         const DecartaPosition *pos,
844         const DecartaAddress *addr,
845         const DecartaBoundary *bound,
846         const DecartaPOIProperty *property,
847         double distance,
848         guint request_id)
849 {
850         DecartaDirectoryRequest* request = g_new0 (DecartaDirectoryRequest, 1);
851         request->search_type = search_type;
852         request->type = type;
853         if (type == DECARTA_DIRECTORY_TYPE_POS) request->pos = decarta_position_copy (pos);
854         else if (type == DECARTA_DIRECTORY_TYPE_ADDRESS) request->addr = decarta_addr_copy (addr);
855         else if (type == DECARTA_DIRECTORY_TYPE_BOUNDARY) request->boundary = decarta_boundary_copy (bound);
856
857         request->property = decarta_poi_property_copy (property);
858         request->distance = distance;
859         request->pref = decarta_poi_preference_copy(pref);
860         if (!request->pref->item) request->pref->item = g_strdup("Distance"); //Distance is default.
861
862         request->request_id = request_id;
863         return request;
864 }
865
866 EXPORT_API void
867 decarta_directory_request_free (DecartaDirectoryRequest *request)
868 {
869         g_return_if_fail (request);
870         if (request->type == DECARTA_DIRECTORY_TYPE_POS) decarta_position_free (request->pos);
871         else if (request->type == DECARTA_DIRECTORY_TYPE_ADDRESS) decarta_address_free (request->addr);
872         else if (request->type == DECARTA_DIRECTORY_TYPE_BOUNDARY) decarta_boundary_free(request->boundary);
873         decarta_poi_property_free (request->property);
874         decarta_poi_preference_free(request->pref);
875         g_free (request);
876 }
877
878 EXPORT_API DecartaDirectoryRequest *
879 decarta_directory_request_copy (const DecartaDirectoryRequest *request)
880 {
881         g_return_val_if_fail (request, NULL);
882         return decarta_directory_request_new (request->pref, request->search_type, request->type, request->pos, request->addr, request->boundary, request->property, request->distance, request->request_id);
883 }
884
885 EXPORT_API DecartaRouteRequest *
886 decarta_route_request_new (DecartaRoutePreference pref,
887         const DecartaGeocode *start, const DecartaGeocode *end,
888         const GList *via_geocode_list,
889         gboolean pos_needed,
890         gboolean instructions_map_needed,
891         gboolean bbox_needed,
892         const DecartaPosition *bbox_pos1,
893         const DecartaPosition *bbox_pos2,
894         gboolean resolution_needed,
895         float resolution,
896         gboolean VR_needed,
897         guint request_id,
898         char *dist_unit, char *rules)
899 {
900         g_return_val_if_fail (start, NULL);
901         g_return_val_if_fail (end, NULL);
902         g_return_val_if_fail (dist_unit, NULL);
903         DecartaRouteRequest *route_req = g_new0 (DecartaRouteRequest, 1);
904         route_req->pref = pref;
905         route_req->start = decarta_geocode_copy (start);
906         route_req->end = decarta_geocode_copy (end);
907         if (route_req->via_geocode_list) route_req->via_geocode_list = decarta_geocode_list_copy (via_geocode_list);
908         route_req->pos_needed = pos_needed;
909         route_req->instructions_map_needed = instructions_map_needed;
910         route_req->request_id = request_id;
911
912         route_req->bbox_needed = bbox_needed;
913         route_req->bbox_pos1 = decarta_position_copy(bbox_pos1);
914         route_req->bbox_pos2 = decarta_position_copy(bbox_pos2);
915         route_req->resolution_needed = resolution_needed;
916         route_req->resolution = resolution;
917         route_req->VR_needed = VR_needed;
918
919         route_req->dist_unit = g_strdup(dist_unit);
920         route_req->rules = g_strdup(rules);
921         return route_req;
922 }
923
924 EXPORT_API DecartaRouteRequest *
925 decarta_route_request_copy (const DecartaRouteRequest *route_req)
926 {
927         g_return_val_if_fail (route_req, NULL);
928         return decarta_route_request_new (route_req->pref, route_req->start, route_req->end,
929                         route_req->via_geocode_list, route_req->pos_needed, route_req->instructions_map_needed,
930                         route_req->bbox_needed, route_req->bbox_pos1, route_req->bbox_pos2,
931                         route_req->resolution_needed, route_req->resolution, route_req->VR_needed, route_req->request_id,
932                         route_req->dist_unit, route_req->rules);
933 }
934
935 EXPORT_API void
936 decarta_route_request_free (DecartaRouteRequest *route_req)
937 {
938         g_return_if_fail (route_req);
939         if (route_req->start)  decarta_geocode_free (route_req->start);
940         if (route_req->end)  decarta_geocode_free (route_req->end);
941         if (route_req->via_geocode_list) decarta_geocode_list_free (route_req->via_geocode_list);
942         if (route_req->bbox_pos1) decarta_position_free (route_req->bbox_pos1);
943         if (route_req->bbox_pos2) decarta_position_free (route_req->bbox_pos2);
944         g_free (route_req->dist_unit);
945         g_free (route_req->rules);
946         g_free (route_req);
947 }