1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-objectid.c DBusObjectID type
4 * Copyright (C) 2003 Red Hat Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-objectid.h"
25 #include "dbus-internals.h"
27 #ifdef DBUS_HAVE_INT64
28 #define VALUE(objid) ((objid)->dbus_do_not_use_dummy1)
29 #define SERVER_MASK DBUS_UINT64_CONSTANT (0xffff000000000000)
30 #define CLIENT_MASK DBUS_UINT64_CONSTANT (0x0000ffff00000000)
31 #define IS_SERVER_MASK DBUS_UINT64_CONSTANT (0x0000000080000000)
32 #define INSTANCE_MASK DBUS_UINT64_CONSTANT (0x000000007fffffff)
33 #define SERVER_BITS(objid) ((dbus_uint16_t) (VALUE (obj_id) >> 48))
34 #define CLIENT_BITS(objid) ((dbus_uint16_t) ((VALUE (obj_id) & CLIENT_MASK) >> 32))
35 #define IS_SERVER_BIT(objid) ((VALUE (obj_id) & IS_SERVER_MASK) != 0)
36 #define INSTANCE_BITS(objid) ((dbus_uint32_t) (VALUE (obj_id) & INSTANCE_MASK))
38 /* We care about the exact packing since in dbus-marshal.c we
39 * just use the DBusObjectID struct as-is.
41 #ifdef WORDS_BIGENDIAN
42 #define HIGH_VALUE(objid) ((objid)->dbus_do_not_use_dummy2)
43 #define LOW_VALUE(objid) ((objid)->dbus_do_not_use_dummy3)
45 #define HIGH_VALUE(objid) ((objid)->dbus_do_not_use_dummy3)
46 #define LOW_VALUE(objid) ((objid)->dbus_do_not_use_dummy2)
48 #define SERVER_MASK (0xffff0000)
49 #define CLIENT_MASK (0x0000ffff)
50 #define IS_SERVER_MASK (0x80000000)
51 #define INSTANCE_MASK (0x7fffffff)
52 #define SERVER_BITS(objid) ((HIGH_VALUE (objid) & SERVER_MASK) >> 16)
53 #define CLIENT_BITS(objid) (HIGH_VALUE (objid) & CLIENT_MASK)
54 #define IS_SERVER_BIT(objid) ((LOW_VALUE (objid) & IS_SERVER_MASK) != 0)
55 #define INSTANCE_BITS(objid) (LOW_VALUE (objid) & INSTANCE_MASK)
59 * @defgroup DBusObjectID object IDs
60 * @ingroup DBusObjectID
61 * @brief object ID datatype
63 * Value type representing an object ID, i.e. an object in the remote
64 * application that can be communicated with.
66 * An object ID has three parts. 16 bits are provided by the server
67 * side of a connection, and used for the high 16 bits of all object
68 * IDs created by the client. 16 bits are provided by the client side
69 * and used as the next 16 bits of all object IDs created by the
70 * client. The next single bit is 1 if the object ID represents an
71 * object on the server side of the connection and 0 otherwise. Then
72 * 31 bits are provided by the side creating an object instance and
73 * differ for each instance created (each app should make a best
74 * effort to avoid recycling the instance values).
76 * 0 is an invalid value for the server bits, the client bits,
77 * and the object instance bits. An object ID is the null ID
78 * if all 64 bits are 0.
84 * Checks whether two object IDs have the same value.
86 * @param a the first object ID
87 * @param b the second object ID
88 * @returns #TRUE if they are equal
91 dbus_object_id_equal (const DBusObjectID *a,
92 const DBusObjectID *b)
94 #ifdef DBUS_HAVE_INT64
95 return VALUE (a) == VALUE (b);
97 return LOW_VALUE (a) == LOW_VALUE (b) && HIGH_VALUE (a) == HIGH_VALUE (b);
102 * Compares two object IDs, appropriate for
103 * qsort(). Higher/lower IDs have no significance,
104 * but the comparison can be used for data structures
105 * that require ordering.
107 * @param a the first object ID
108 * @param b the second object ID
109 * @returns -1, 0, 1 as with strcmp()
112 dbus_object_id_compare (const DBusObjectID *a,
113 const DBusObjectID *b)
115 #ifdef DBUS_HAVE_INT64
116 if (VALUE (a) > VALUE (b))
118 else if (VALUE (a) < VALUE (b))
123 if (HIGH_VALUE (a) > HIGH_VALUE (b))
125 else if (HIGH_VALUE (a) < HIGH_VALUE (b))
127 else if (LOW_VALUE (a) > LOW_VALUE (b))
129 else if (LOW_VALUE (a) < LOW_VALUE (b))
138 * An object ID contains 64 bits of data. This function
139 * returns the 16 bits that were provided by the server
140 * side of the connection.
142 * @param obj_id the object ID
143 * @returns the server bits of the ID
147 dbus_object_id_get_server_bits (const DBusObjectID *obj_id)
149 return SERVER_BITS (obj_id);
153 * An object ID contains 64 bits of data. This function
154 * returns the 16 bits that were provided by the client
155 * side of the connection.
157 * @param obj_id the object ID
158 * @returns the client bits of the ID
162 dbus_object_id_get_client_bits (const DBusObjectID *obj_id)
164 return CLIENT_BITS (obj_id);
168 * An object ID contains 64 bits of data. This function
169 * returns the bit flagging whether the object ID comes
170 * from the client or the server side of the connection.
172 * There is no secure guarantee that the bit is accurate;
173 * object ID values are simply conventional, to make
174 * collisions relatively unlikely.
176 * @param obj_id the object ID
177 * @returns the server-side bit of the ID
181 dbus_object_id_get_is_server_bit (const DBusObjectID *obj_id)
183 return IS_SERVER_BIT (obj_id);
187 * An object ID contains 64 bits of data. This function
188 * returns the 31 bits that identify the object instance.
190 * @param obj_id the object ID
191 * @returns the instance bits of the ID
195 dbus_object_id_get_instance_bits (const DBusObjectID *obj_id)
197 return INSTANCE_BITS (obj_id);
201 * An object ID contains 64 bits of data. This function sets the 16
202 * bits provided by the server side of a connection.
204 * @param obj_id the object ID
205 * @param value the new value of the server bits
209 dbus_object_id_set_server_bits (DBusObjectID *obj_id,
212 #ifdef DBUS_HAVE_INT64
213 VALUE (obj_id) &= ~ SERVER_MASK;
214 VALUE (obj_id) |= ((dbus_uint64_t) value) << 48;
216 HIGH_VALUE (obj_id) &= ~ SERVER_MASK;
217 HIGH_VALUE (obj_id) |= ((dbus_uint32_t) value) << 16;
222 * An object ID contains 64 bits of data. This function sets the 16
223 * bits provided by the client side of a connection.
225 * @param obj_id the object ID
226 * @param value the new value of the client bits
230 dbus_object_id_set_client_bits (DBusObjectID *obj_id,
233 #ifdef DBUS_HAVE_INT64
234 VALUE (obj_id) &= ~ CLIENT_MASK;
235 VALUE (obj_id) |= ((dbus_uint64_t) value) << 32;
237 HIGH_VALUE (obj_id) &= ~ CLIENT_MASK;
238 HIGH_VALUE (obj_id) |= (dbus_uint32_t) value;
243 * An object ID contains 64 bits of data. This function sets the
244 * single bit that flags an instance as server-side or client-side.
246 * @param obj_id the object ID
247 * @param value the new value of the server-side bit
251 dbus_object_id_set_is_server_bit (DBusObjectID *obj_id,
254 #ifdef DBUS_HAVE_INT64
256 VALUE (obj_id) |= IS_SERVER_MASK;
258 VALUE (obj_id) &= ~ IS_SERVER_MASK;
261 LOW_VALUE (obj_id) |= IS_SERVER_MASK;
263 LOW_VALUE (obj_id) &= ~ IS_SERVER_MASK;
268 * An object ID contains 64 bits of data. This function sets the 31
269 * bits identifying the object instance.
271 * @param obj_id the object ID
272 * @param value the new value of the instance bits
276 dbus_object_id_set_instance_bits (DBusObjectID *obj_id,
279 #ifdef DBUS_HAVE_INT64
280 VALUE (obj_id) &= ~ INSTANCE_MASK;
281 VALUE (obj_id) |= (dbus_uint64_t) value;
283 LOW_VALUE (obj_id) &= ~ INSTANCE_MASK;
284 LOW_VALUE (obj_id) |= (dbus_uint32_t) value;
289 * Set the object ID to an invalid value that cannot
290 * correspond to a valid object.
292 * @param obj_id the object ID
295 dbus_object_id_set_null (DBusObjectID *obj_id)
297 memset (obj_id, '\0', sizeof (DBusObjectID));
301 * Check whether the object ID is set to a null value
303 * @param obj_id the object ID
304 * @returns #TRUE if null
307 dbus_object_id_is_null (const DBusObjectID *obj_id)
309 #ifdef DBUS_HAVE_INT64
310 return VALUE (obj_id) == 0;
312 return HIGH_VALUE (obj_id) == 0 && LOW_VALUE (obj_id) == 0;
316 #ifdef DBUS_HAVE_INT64
318 * An object ID contains 64 bits of data. This function
319 * returns all of them as a 64-bit integer.
321 * Use this function only if you are willing to limit portability to
322 * compilers with a 64-bit type (this includes C99 compilers and
323 * almost all other compilers).
325 * This function only exists if DBUS_HAVE_INT64 is defined.
327 * @param obj_id the object ID
328 * @returns the object ID as a 64-bit integer.
331 dbus_object_id_get_as_integer (const DBusObjectID *obj_id)
333 return VALUE (obj_id);
337 * An object ID contains 64 bits of data. This function sets all of
338 * them as a 64-bit integer.
340 * Use this function only if you are willing to limit portability to
341 * compilers with a 64-bit type (this includes C99 compilers and
342 * almost all other compilers).
344 * This function only exists if #DBUS_HAVE_INT64 is defined.
346 * @param obj_id the object ID
347 * @param value the new value of the object ID
350 dbus_object_id_set_as_integer (DBusObjectID *obj_id,
353 VALUE (obj_id) = value;
355 #endif /* DBUS_HAVE_INT64 */
359 #ifdef DBUS_BUILD_TESTS
360 #include "dbus-test.h"
364 * Test for object ID routines.
366 * @returns #TRUE on success
369 _dbus_object_id_test (void)
374 /* Check basic get/set */
376 dbus_object_id_set_server_bits (&tmp, 340);
377 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 340);
379 dbus_object_id_set_client_bits (&tmp, 1492);
380 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 1492);
381 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 340);
383 dbus_object_id_set_is_server_bit (&tmp, TRUE);
384 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 1492);
385 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 340);
386 _dbus_assert (dbus_object_id_get_is_server_bit (&tmp) == TRUE);
388 dbus_object_id_set_instance_bits (&tmp, 2001);
389 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 1492);
390 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 340);
391 _dbus_assert (dbus_object_id_get_is_server_bit (&tmp) == TRUE);
392 _dbus_assert (dbus_object_id_get_instance_bits (&tmp) == 2001);
394 /* check equality check */
396 _dbus_assert (dbus_object_id_equal (&tmp, &tmp2));
398 /* check get/set as integer */
399 #ifdef DBUS_HAVE_INT64
400 _dbus_assert (dbus_object_id_get_as_integer (&tmp) ==
401 ((DBUS_UINT64_CONSTANT (340) << 48) |
402 (DBUS_UINT64_CONSTANT (1492) << 32) |
403 (DBUS_UINT64_CONSTANT (1) << 31) |
404 (DBUS_UINT64_CONSTANT (2001))));
406 dbus_object_id_set_as_integer (&tmp, _DBUS_UINT64_MAX);
407 _dbus_assert (dbus_object_id_get_as_integer (&tmp) ==
409 _dbus_assert (dbus_object_id_get_server_bits (&tmp) ==
411 _dbus_assert (dbus_object_id_get_client_bits (&tmp) ==
413 _dbus_assert (dbus_object_id_get_is_server_bit (&tmp) ==
415 _dbus_assert (dbus_object_id_get_instance_bits (&tmp) ==
418 dbus_object_id_set_as_integer (&tmp, 1);
419 dbus_object_id_set_as_integer (&tmp2, 2);
420 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == -1);
421 dbus_object_id_set_as_integer (&tmp2, 0);
422 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 1);
423 dbus_object_id_set_as_integer (&tmp2, 1);
424 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 0);
427 /* Check comparison */
430 dbus_object_id_set_server_bits (&tmp, 1);
431 dbus_object_id_set_server_bits (&tmp2, 2);
432 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == -1);
433 dbus_object_id_set_server_bits (&tmp2, 0);
434 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 1);
435 dbus_object_id_set_server_bits (&tmp2, 1);
436 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 0);
438 dbus_object_id_set_client_bits (&tmp, 1);
440 dbus_object_id_set_client_bits (&tmp2, 2);
441 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == -1);
442 dbus_object_id_set_client_bits (&tmp2, 0);
443 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 1);
444 dbus_object_id_set_client_bits (&tmp2, 1);
445 _dbus_assert (dbus_object_id_compare (&tmp, &tmp2) == 0);
447 /* Check get/set again with high-limit numbers */
449 dbus_object_id_set_server_bits (&tmp, 0xf0f0);
450 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 0xf0f0);
452 dbus_object_id_set_client_bits (&tmp, 0xf00f);
453 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 0xf00f);
454 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 0xf0f0);
456 dbus_object_id_set_is_server_bit (&tmp, TRUE);
457 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 0xf00f);
458 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 0xf0f0);
459 _dbus_assert (dbus_object_id_get_is_server_bit (&tmp) == TRUE);
461 dbus_object_id_set_instance_bits (&tmp, 0x7fffffff);
462 _dbus_assert (dbus_object_id_get_client_bits (&tmp) == 0xf00f);
463 _dbus_assert (dbus_object_id_get_server_bits (&tmp) == 0xf0f0);
464 _dbus_assert (dbus_object_id_get_is_server_bit (&tmp) == TRUE);
465 _dbus_assert (dbus_object_id_get_instance_bits (&tmp) == 0x7fffffff);
470 #endif /* DBUS_BUILD_TESTS */