1 /*
2  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
3  * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
4  *
5  * This library is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include "evolution-data-server-config.h"
20 
21 /**
22  * SECTION:e-cal-component-id
23  * @short_description: An ECalComponentId structure
24  * @include: libecal/libecal.h
25  *
26  * Contains functions to work with the #ECalComponentId structure.
27  **/
28 
29 #include "e-cal-component-id.h"
30 
31 G_DEFINE_BOXED_TYPE (ECalComponentId, e_cal_component_id, e_cal_component_id_copy, e_cal_component_id_free)
32 
33 struct _ECalComponentId {
34 	gchar *uid;
35 	gchar *rid;
36 };
37 
38 /**
39  * e_cal_component_id_new:
40  * @uid: a unique ID string
41  * @rid: (nullable): an optional recurrence ID string
42  *
43  * Creates a new #ECalComponentId from @uid and @rid, which should be
44  * freed with e_cal_component_id_free().
45  *
46  * Returns: (transfer full): an #ECalComponentId
47  *
48  * Since: 3.10
49  **/
50 ECalComponentId *
e_cal_component_id_new(const gchar * uid,const gchar * rid)51 e_cal_component_id_new (const gchar *uid,
52                         const gchar *rid)
53 {
54 	g_return_val_if_fail (uid != NULL, NULL);
55 
56 	/* Normalize an empty recurrence ID to NULL. */
57 	if (rid && !*rid)
58 		rid = NULL;
59 
60 	return e_cal_component_id_new_take (g_strdup (uid), g_strdup (rid));
61 }
62 
63 /**
64  * e_cal_component_id_new_take:
65  * @uid: (transfer full): a unique ID string
66  * @rid: (transfer full) (nullable): an optional recurrence ID string
67  *
68  * Creates a new #ECalComponentId from @uid and @rid, which should be
69  * freed with e_cal_component_id_free(). The function assumes ownership
70  * of @uid and @rid parameters.
71  *
72  * Returns: (transfer full): an #ECalComponentId
73  *
74  * Since: 3.34
75  **/
76 ECalComponentId *
e_cal_component_id_new_take(gchar * uid,gchar * rid)77 e_cal_component_id_new_take (gchar *uid,
78 			     gchar *rid)
79 {
80 	ECalComponentId *id;
81 
82 	g_return_val_if_fail (uid != NULL, NULL);
83 
84 	/* Normalize an empty recurrence ID to NULL. */
85 	if (rid && !*rid) {
86 		g_free (rid);
87 		rid = NULL;
88 	}
89 
90 	id = g_slice_new0 (ECalComponentId);
91 	id->uid = uid;
92 	id->rid = rid;
93 
94 	return id;
95 }
96 
97 /**
98  * e_cal_component_id_copy:
99  * @id: (not nullable): an #ECalComponentId
100  *
101  * Returns a newly allocated copy of @id, which should be freed with
102  * e_cal_component_id_free().
103  *
104  * Returns: (transfer full): a newly allocated copy of @id
105  *
106  * Since: 3.10
107  **/
108 ECalComponentId *
e_cal_component_id_copy(const ECalComponentId * id)109 e_cal_component_id_copy (const ECalComponentId *id)
110 {
111 	g_return_val_if_fail (id != NULL, NULL);
112 
113 	return e_cal_component_id_new (id->uid, id->rid);
114 }
115 
116 /**
117  * e_cal_component_id_free: (skip)
118  * @id: (type ECalComponentId) (transfer full) (nullable): an #ECalComponentId
119  *
120  * Free the @id, previously created by e_cal_component_id_new(),
121  * e_cal_component_id_new_take() or e_cal_component_id_copy().
122  **/
123 void
e_cal_component_id_free(gpointer id)124 e_cal_component_id_free (gpointer id)
125 {
126 	ECalComponentId *eid = id;
127 
128 	if (eid) {
129 		g_free (eid->uid);
130 		g_free (eid->rid);
131 		g_slice_free (ECalComponentId, eid);
132 	}
133 }
134 
135 /**
136  * e_cal_component_id_hash:
137  * @id: (type ECalComponentId): an #ECalComponentId
138  *
139  * Generates a hash value for @id.
140  *
141  * Returns: a hash value for @id
142  *
143  * Since: 3.10
144  **/
145 guint
e_cal_component_id_hash(gconstpointer id)146 e_cal_component_id_hash (gconstpointer id)
147 {
148 	const ECalComponentId *eid = id;
149 	guint uid_hash;
150 	guint rid_hash;
151 
152 	g_return_val_if_fail (id != NULL, 0);
153 
154 	uid_hash = g_str_hash (eid->uid);
155 	rid_hash = eid->rid ? g_str_hash (eid->rid) : 0;
156 
157 	return uid_hash ^ rid_hash;
158 }
159 
160 /**
161  * e_cal_component_id_equal:
162  * @id1: (type ECalComponentId): the first #ECalComponentId
163  * @id2: (type ECalComponentId): the second #ECalComponentId
164  *
165  * Compares two #ECalComponentId structs for equality.
166  *
167  * Returns: %TRUE if @id1 and @id2 are equal
168  *
169  * Since: 3.10
170  **/
171 gboolean
e_cal_component_id_equal(gconstpointer id1,gconstpointer id2)172 e_cal_component_id_equal (gconstpointer id1,
173                           gconstpointer id2)
174 {
175 	const ECalComponentId *eid1 = id1, *eid2 = id2;
176 	gboolean uids_equal;
177 	gboolean rids_equal;
178 
179 	if (id1 == id2)
180 		return TRUE;
181 
182 	/* Safety check before we dereference. */
183 	g_return_val_if_fail (id1 != NULL, FALSE);
184 	g_return_val_if_fail (id2 != NULL, FALSE);
185 
186 	uids_equal = (g_strcmp0 (eid1->uid, eid2->uid) == 0);
187 	rids_equal = (g_strcmp0 (eid1->rid, eid2->rid) == 0);
188 
189 	return uids_equal && rids_equal;
190 }
191 
192 /**
193  * e_cal_component_id_get_uid:
194  * @id: an #ECalComponentId
195  *
196  * Returns: (transfer none): The UID part of the @id. The returned
197  *    string is owned by @id and it's valid until it's changed
198  *    with e_cal_component_id_set_uid() or until the @id is freed.
199  *
200  * Since: 3.34
201  **/
202 const gchar *
e_cal_component_id_get_uid(const ECalComponentId * id)203 e_cal_component_id_get_uid (const ECalComponentId *id)
204 {
205 	g_return_val_if_fail (id != NULL, NULL);
206 
207 	return id->uid;
208 }
209 
210 /**
211  * e_cal_component_id_set_uid:
212  * @id: an #ECalComponentId
213  * @uid: (not nullable): the UID to set
214  *
215  * Sets the UID part of the @id.
216  *
217  * Since: 3.34
218  **/
219 void
e_cal_component_id_set_uid(ECalComponentId * id,const gchar * uid)220 e_cal_component_id_set_uid (ECalComponentId *id,
221 			    const gchar *uid)
222 {
223 	g_return_if_fail (id != NULL);
224 	g_return_if_fail (uid != NULL);
225 
226 	if (g_strcmp0 (id->uid, uid) != 0) {
227 		g_free (id->uid);
228 		id->uid = g_strdup (uid);
229 	}
230 }
231 
232 /**
233  * e_cal_component_id_get_rid:
234  * @id: an #ECalComponentId
235  *
236  * Returns: (transfer none) (nullable): The RECURRENCE-ID part of the @id.
237  *    The returned string is owned by @id and it's valid until it's
238  *    changed with e_cal_component_id_set_rid() or until the @id is freed.
239  *
240  * Since: 3.34
241  **/
242 const gchar *
e_cal_component_id_get_rid(const ECalComponentId * id)243 e_cal_component_id_get_rid (const ECalComponentId *id)
244 {
245 	g_return_val_if_fail (id != NULL, NULL);
246 
247 	return id->rid;
248 }
249 
250 /**
251  * e_cal_component_id_set_rid:
252  * @id: an #ECalComponentId
253  * @rid: (nullable): the RECURRENCE-ID to set
254  *
255  * Sets the RECURRENCE-ID part of the @id. The @rid can be %NULL
256  * or an empty string, where both are treated as %NULL, which
257  * means the @id has not RECURRENCE-ID.
258  *
259  * Since: 3.34
260  **/
261 void
e_cal_component_id_set_rid(ECalComponentId * id,const gchar * rid)262 e_cal_component_id_set_rid (ECalComponentId *id,
263 			    const gchar *rid)
264 {
265 	g_return_if_fail (id != NULL);
266 
267 	if (g_strcmp0 (id->rid, rid) != 0) {
268 		g_free (id->rid);
269 		id->rid = (rid && *rid) ? g_strdup (rid) : NULL;
270 	}
271 }
272