1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * lt-region.c
4  * Copyright (C) 2011-2012 Akira TAGOH
5  *
6  * Authors:
7  *   Akira TAGOH  <akira@tagoh.org>
8  *
9  * You may distribute under the terms of either the GNU
10  * Lesser General Public License or the Mozilla Public
11  * License, as specified in the README file.
12  */
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16 
17 #include <stdlib.h>
18 #include <string.h>
19 #include "lt-mem.h"
20 #include "lt-messages.h"
21 #include "lt-string.h"
22 #include "lt-utils.h"
23 #include "lt-region.h"
24 #include "lt-region-private.h"
25 
26 
27 /**
28  * SECTION:lt-region
29  * @Short_Description: A container class for Region subtag
30  * @Title: Container - Region
31  *
32  * This container class provides a data access to Region subtag entry.
33  */
34 struct _lt_region_t {
35 	lt_mem_t  parent;
36 	char     *tag;
37 	char     *description;
38 	char     *preferred_tag;
39 };
40 
41 
42 /*< private >*/
43 
44 /*< protected >*/
45 lt_region_t *
lt_region_create(void)46 lt_region_create(void)
47 {
48 	lt_region_t *retval = lt_mem_alloc_object(sizeof (lt_region_t));
49 
50 	return retval;
51 }
52 
53 void
lt_region_set_name(lt_region_t * region,const char * description)54 lt_region_set_name(lt_region_t *region,
55 		   const char  *description)
56 {
57 	lt_return_if_fail (region != NULL);
58 	lt_return_if_fail (description != NULL);
59 
60 	if (region->description)
61 		lt_mem_delete_ref(&region->parent, region->description);
62 	region->description = strdup(description);
63 	lt_mem_add_ref(&region->parent, region->description, free);
64 }
65 
66 void
lt_region_set_tag(lt_region_t * region,const char * subtag)67 lt_region_set_tag(lt_region_t *region,
68 		  const char  *subtag)
69 {
70 	lt_return_if_fail (region != NULL);
71 	lt_return_if_fail (subtag != NULL);
72 
73 	if (region->tag)
74 		lt_mem_delete_ref(&region->parent, region->tag);
75 	region->tag = strdup(subtag);
76 	lt_mem_add_ref(&region->parent, region->tag, free);
77 }
78 
79 void
lt_region_set_preferred_tag(lt_region_t * region,const char * subtag)80 lt_region_set_preferred_tag(lt_region_t *region,
81 			    const char  *subtag)
82 {
83 	lt_return_if_fail (region != NULL);
84 	lt_return_if_fail (subtag != NULL);
85 
86 	if (region->preferred_tag)
87 		lt_mem_delete_ref(&region->parent, region->preferred_tag);
88 	region->preferred_tag = strdup(subtag);
89 	lt_mem_add_ref(&region->parent, region->preferred_tag, free);
90 }
91 
92 /*< public >*/
93 /**
94  * lt_region_ref:
95  * @region: a #lt_region_t.
96  *
97  * Increases the reference count of @region.
98  *
99  * Returns: (transfer none): the same @region object.
100  */
101 lt_region_t *
lt_region_ref(lt_region_t * region)102 lt_region_ref(lt_region_t *region)
103 {
104 	lt_return_val_if_fail (region != NULL, NULL);
105 
106 	return lt_mem_ref(&region->parent);
107 }
108 
109 /**
110  * lt_region_unref:
111  * @region: a #lt_region_t.
112  *
113  * Decreases the reference count of @region. when its reference count
114  * drops to 0, the object is finalized (i.e. its memory is freed).
115  */
116 void
lt_region_unref(lt_region_t * region)117 lt_region_unref(lt_region_t *region)
118 {
119 	if (region)
120 		lt_mem_unref(&region->parent);
121 }
122 
123 /**
124  * lt_region_get_name:
125  * @region: a #lt_region_t.
126  *
127  * Obtains the description of the subtag.
128  *
129  * Returns: a description string.
130  */
131 const char *
lt_region_get_name(const lt_region_t * region)132 lt_region_get_name(const lt_region_t *region)
133 {
134 	lt_return_val_if_fail (region != NULL, NULL);
135 
136 	return region->description;
137 }
138 
139 /**
140  * lt_region_get_better_tag:
141  * @region: a #lt_region_t.
142  *
143  * Obtains the better tag for use. this is a convenient function to get
144  * the preferred-value if available.
145  *
146  * Returns: a tag string.
147  */
148 const char *
lt_region_get_better_tag(const lt_region_t * region)149 lt_region_get_better_tag(const lt_region_t *region)
150 {
151 	const char *retval = lt_region_get_preferred_tag(region);
152 
153 	if (!retval)
154 		retval = lt_region_get_tag(region);
155 
156 	return retval;
157 }
158 
159 /**
160  * lt_region_get_tag:
161  * @region: a #lt_region_t.
162  *
163  * Obtains the tag name.
164  *
165  * Returns: a tag string.
166  */
167 const char *
lt_region_get_tag(const lt_region_t * region)168 lt_region_get_tag(const lt_region_t *region)
169 {
170 	lt_return_val_if_fail (region != NULL, NULL);
171 
172 	return region->tag;
173 }
174 
175 /**
176  * lt_region_get_preferred_tag:
177  * @region: a #lt_region_t.
178  *
179  * Obtains the preferred-value. this is available only when the tag is
180  * marked as deprecated.
181  *
182  * Returns: a preferred-value for the tag or %NULL.
183  */
184 const char *
lt_region_get_preferred_tag(const lt_region_t * region)185 lt_region_get_preferred_tag(const lt_region_t *region)
186 {
187 	lt_return_val_if_fail (region != NULL, NULL);
188 
189 	return region->preferred_tag;
190 }
191 
192 /**
193  * lt_region_dump:
194  * @region: a #lt_region_t.
195  *
196  * Dumps the container information to the standard output.
197  */
198 void
lt_region_dump(const lt_region_t * region)199 lt_region_dump(const lt_region_t *region)
200 {
201 	lt_string_t *string = lt_string_new(NULL);
202 	const char *preferred = lt_region_get_preferred_tag(region);
203 
204 	if (preferred) {
205 		if (lt_string_length(string) == 0)
206 			lt_string_append(string, " (");
207 		lt_string_append_printf(string, "preferred-value: %s", preferred);
208 	}
209 	if (lt_string_length(string) > 0)
210 		lt_string_append(string, ")");
211 
212 	lt_info("Region: %s [%s]%s",
213 		lt_region_get_tag(region),
214 		lt_region_get_name(region),
215 		lt_string_value(string));
216 
217 	lt_string_unref(string);
218 }
219 
220 /**
221  * lt_region_compare:
222  * @v1: a #lt_region_t.
223  * @v2: a #lt_region_t.
224  *
225  * Compare if @v1 and @v2 is the same object or not.
226  *
227  * Returns: %TRUE if it's the same, otherwise %FALSE.
228  */
229 lt_bool_t
lt_region_compare(const lt_region_t * v1,const lt_region_t * v2)230 lt_region_compare(const lt_region_t *v1,
231 		  const lt_region_t *v2)
232 {
233 	const char *s1, *s2;
234 
235 	if (v1 == v2)
236 		return TRUE;
237 
238 	s1 = v1 ? lt_region_get_tag(v1) : NULL;
239 	s2 = v2 ? lt_region_get_tag(v2) : NULL;
240 
241 	if (lt_strcmp0(s1, "*") == 0 ||
242 	    lt_strcmp0(s2, "*") == 0)
243 		return TRUE;
244 
245 	return lt_strcmp0(s1, s2) == 0;
246 }
247