25 #include "dbus-object-tree.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-internals.h"
28 #include "dbus-hash.h"
29 #include "dbus-protocol.h"
30 #include "dbus-string.h"
107 tree->
root = _dbus_object_subtree_new (
"/",
NULL,
NULL);
160 #define VERBOSE_FIND 0
166 int *index_in_parent,
172 return_deepest_match = exact_match !=
NULL;
174 _dbus_assert (!(return_deepest_match && create_if_not_found));
179 _dbus_verbose (
" path exhausted, returning %s\n",
182 if (exact_match !=
NULL)
188 _dbus_verbose (
" searching children of %s for %s\n",
189 subtree->
name, path[0]);
202 _dbus_verbose (
" %s cmp %s = %d\n",
212 _dbus_verbose (
" storing parent index %d\n", k);
214 *index_in_parent = k;
217 if (return_deepest_match)
221 next = find_subtree_recurse (subtree->
subtrees[k],
222 &path[1], create_if_not_found,
223 index_in_parent, exact_match);
228 _dbus_verbose (
" no deeper match found, returning %s\n",
231 if (exact_match !=
NULL)
232 *exact_match =
FALSE;
239 return find_subtree_recurse (subtree->
subtrees[k],
240 &path[1], create_if_not_found,
241 index_in_parent, exact_match);
254 _dbus_verbose (
" no match found, current tree %s, create_if_not_found = %d\n",
255 subtree->
name, create_if_not_found);
258 if (create_if_not_found)
261 int child_pos, new_n_subtrees;
264 _dbus_verbose (
" creating subtree %s\n",
268 child = _dbus_object_subtree_new (path[0],
276 int new_max_subtrees;
282 if (new_subtrees ==
NULL)
284 _dbus_object_subtree_unref (child);
295 new_n_subtrees <= subtree->max_subtrees);
296 if (child_pos + 1 < new_n_subtrees)
298 memmove (&subtree->
subtrees[child_pos+1],
300 (new_n_subtrees - child_pos - 1) *
303 subtree->
subtrees[child_pos] = child;
306 *index_in_parent = child_pos;
310 return find_subtree_recurse (child,
311 &path[1], create_if_not_found,
312 index_in_parent, exact_match);
316 if (exact_match !=
NULL)
317 *exact_match =
FALSE;
325 int *index_in_parent)
330 _dbus_verbose (
"Looking for exact registered subtree\n");
333 subtree = find_subtree_recurse (tree->
root, path,
FALSE, index_in_parent,
NULL);
346 _dbus_verbose (
"Looking for subtree\n");
357 _dbus_verbose (
"Looking for deepest handler\n");
361 *exact_match =
FALSE;
363 return find_subtree_recurse (tree->
root, path,
FALSE,
NULL, exact_match);
371 _dbus_verbose (
"Ensuring subtree\n");
376 static char *flatten_path (
const char **path);
404 subtree = ensure_subtree (tree, path);
407 _DBUS_SET_OOM (error);
415 char *complete_path = flatten_path (path);
418 "A handler is already registered for %s",
419 complete_path ? complete_path
420 :
"(cannot represent path: out of memory!)");
455 unregister_function =
NULL;
458 subtree = find_subtree (tree, path, &i);
460 #ifndef DBUS_DISABLE_CHECKS
463 _dbus_warn (
"Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n",
464 path[0] ? path[0] :
"null",
465 path[1] ? path[1] :
"null");
498 _dbus_object_subtree_unref (subtree);
506 #ifdef DBUS_BUILD_TESTS
511 _dbus_verbose (
"unlock\n");
515 if (unregister_function)
516 (* unregister_function) (connection, user_data);
518 #ifdef DBUS_BUILD_TESTS
540 free_subtree_recurse (connection, child);
553 _dbus_object_subtree_unref (subtree);
573 const char **parent_path,
574 char ***child_entries)
582 *child_entries =
NULL;
584 subtree = lookup_subtree (tree, parent_path);
596 while (i < subtree->n_subtrees)
599 if (retval[i] ==
NULL)
611 *child_entries = retval;
612 return retval !=
NULL;
626 const char *v_STRING;
631 already_unlocked =
FALSE;
633 _dbus_verbose (
" considering default Introspect() handler...\n");
641 #ifdef DBUS_BUILD_TESTS
645 _dbus_verbose (
"unlock\n");
652 _dbus_verbose (
" using default Introspect() handler!\n");
656 #ifdef DBUS_BUILD_TESTS
660 _dbus_verbose (
"unlock\n");
670 if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
680 while (children[i] !=
NULL)
701 #ifdef DBUS_BUILD_TESTS
705 already_unlocked =
TRUE;
714 #ifdef DBUS_BUILD_TESTS
718 if (!already_unlocked)
720 _dbus_verbose (
"unlock\n");
758 _dbus_verbose (
"Dispatch of message by object path\n");
764 #ifdef DBUS_BUILD_TESTS
768 _dbus_verbose (
"unlock\n");
772 _dbus_verbose (
"No memory to get decomposed path\n");
779 #ifdef DBUS_BUILD_TESTS
783 _dbus_verbose (
"unlock\n");
787 _dbus_verbose (
"No path field in message\n");
792 subtree = find_handler (tree, (
const char**) path, &exact_match);
798 while (subtree !=
NULL)
802 _dbus_object_subtree_ref (subtree);
808 _dbus_object_subtree_unref (subtree);
809 goto free_and_return;
814 subtree = subtree->
parent;
817 _dbus_verbose (
"%d handlers in the path tree for this message\n",
828 subtree = link->
data;
842 _dbus_verbose (
" (invoking a handler)\n");
845 #ifdef DBUS_BUILD_TESTS
849 _dbus_verbose (
"unlock\n");
858 result = (* message_function) (tree->
connection,
862 #ifdef DBUS_BUILD_TESTS
868 goto free_and_return;
880 result = handle_default_introspect_and_unlock (tree, message,
881 (
const char**) path);
885 #ifdef DBUS_BUILD_TESTS
889 _dbus_verbose (
"unlock\n");
897 _dbus_object_subtree_unref (link->
data);
925 subtree = find_handler (tree, (
const char**) path, &exact_match);
927 if ((subtree ==
NULL) || !exact_match)
929 _dbus_verbose (
"No object at specified path found\n");
943 allocate_subtree_object (
const char *name)
958 memcpy (subtree->
name, name, len + 1);
964 _dbus_object_subtree_new (
const char *name,
970 subtree = allocate_subtree_object (name);
1038 const char **parent_path,
1039 char ***child_entries)
1043 result = _dbus_object_tree_list_registered_unlocked (tree,
1047 #ifdef DBUS_BUILD_TESTS
1051 _dbus_verbose (
"unlock\n");
1060 #define VERBOSE_DECOMPOSE 0
1085 #if VERBOSE_DECOMPOSE
1086 _dbus_verbose (
"Decomposing path \"%s\"\n",
1103 retval =
dbus_new0 (
char*, n_components + 1);
1109 if (n_components == 0)
1113 while (comp < n_components)
1121 while (j < len && data[j] !=
'/')
1129 #if VERBOSE_DECOMPOSE
1130 _dbus_verbose (
" (component in [%d,%d))\n",
1135 if (retval[comp] ==
NULL)
1140 retval[comp][j-i] =
'\0';
1141 #if VERBOSE_DECOMPOSE
1142 _dbus_verbose (
" (component %d = \"%s\")\n",
1143 comp, retval[comp]);
1153 *path_len = n_components;
1161 flatten_path (
const char **path)
1169 if (path[0] ==
NULL)
1204 #ifdef DBUS_BUILD_TESTS
1206 #ifndef DOXYGEN_SHOULD_SKIP_THIS
1208 #include "dbus-test.h"
1220 static StrComparison
1221 path_contains (
const char **container,
1227 while (child[i] !=
NULL)
1231 if (container[i] ==
NULL)
1240 v = strcmp (container[i], child[i]);
1243 return STR_DIFFERENT;
1253 if (container[i] ==
NULL)
1256 return STR_DIFFERENT;
1269 _dbus_verbose (
" ");
1273 _dbus_verbose (
"%s (%d children)\n",
1277 while (i < subtree->n_subtrees)
1279 spew_subtree_recurse (subtree->
subtrees[i], indent + 2);
1288 spew_subtree_recurse (tree->
root, 0);
1308 TreeTestData *ttd = user_data;
1310 ttd->handler_unregistered =
TRUE;
1318 TreeTestData *ttd = user_data;
1320 ttd->message_handled =
TRUE;
1330 TreeTestData *tree_test_data)
1333 test_message_function,
NULL };
1335 tree_test_data[i].message_handled =
FALSE;
1336 tree_test_data[i].handler_unregistered =
FALSE;
1337 tree_test_data[i].handler_fallback = fallback;
1338 tree_test_data[i].path = path;
1347 &tree_test_data[i]);
1356 TreeTestData *tree_test_data,
1366 flat = flatten_path (path);
1372 "org.freedesktop.TestInterface",
1375 if (message ==
NULL)
1379 while (j < n_test_data)
1381 tree_test_data[j].message_handled =
FALSE;
1392 while (j < n_test_data)
1394 if (tree_test_data[j].message_handled)
1396 if (tree_test_data[j].handler_fallback)
1398 path) != STR_DIFFERENT);
1400 _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL);
1404 if (tree_test_data[j].handler_fallback)
1406 path) == STR_DIFFERENT);
1408 _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL);
1425 string_array_length (
const char **array)
1428 for (i = 0; array[i]; i++) ;
1435 const char *result[20];
1436 } DecomposePathTest;
1438 static DecomposePathTest decompose_tests[] = {
1439 {
"/foo", {
"foo",
NULL } },
1440 {
"/foo/bar", {
"foo",
"bar",
NULL } },
1442 {
"/a/b", {
"a",
"b",
NULL } },
1443 {
"/a/b/c", {
"a",
"b",
"c",
NULL } },
1444 {
"/a/b/c/d", {
"a",
"b",
"c",
"d",
NULL } },
1445 {
"/foo/bar/q", {
"foo",
"bar",
"q",
NULL } },
1446 {
"/foo/bar/this/is/longer", {
"foo",
"bar",
"this",
"is",
"longer",
NULL } }
1450 run_decompose_tests (
void)
1462 strlen (decompose_tests[i].path),
1463 &result, &result_len))
1466 expected_len = string_array_length (decompose_tests[i].result);
1468 if (result_len != (
int) string_array_length ((
const char**)result) ||
1469 expected_len != result_len ||
1470 path_contains (decompose_tests[i].result,
1471 (
const char**) result) != STR_EQUAL)
1473 int real_len = string_array_length ((
const char**)result);
1474 _dbus_warn (
"Expected decompose of %s to have len %d, returned %d, appears to have %d\n",
1475 decompose_tests[i].path, expected_len, result_len,
1477 _dbus_warn (
"Decompose resulted in elements: { ");
1479 while (i < real_len)
1482 (i + 1) == real_len ?
"" :
", ");
1498 object_tree_test_iteration (
void *data)
1500 const char *path0[] = {
NULL };
1501 const char *path1[] = {
"foo",
NULL };
1502 const char *path2[] = {
"foo",
"bar",
NULL };
1503 const char *path3[] = {
"foo",
"bar",
"baz",
NULL };
1504 const char *path4[] = {
"foo",
"bar",
"boo",
NULL };
1505 const char *path5[] = {
"blah",
NULL };
1506 const char *path6[] = {
"blah",
"boof",
NULL };
1507 const char *path7[] = {
"blah",
"boof",
"this",
"is",
"really",
"long",
NULL };
1508 const char *path8[] = {
"childless",
NULL };
1510 TreeTestData tree_test_data[9];
1514 if (!run_decompose_tests ())
1523 if (!do_register (tree, path0,
TRUE, 0, tree_test_data))
1536 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
1537 _dbus_assert (find_handler (tree, path1, &exact_match) == tree->
root && !exact_match);
1538 _dbus_assert (find_handler (tree, path2, &exact_match) == tree->
root && !exact_match);
1539 _dbus_assert (find_handler (tree, path3, &exact_match) == tree->
root && !exact_match);
1540 _dbus_assert (find_handler (tree, path4, &exact_match) == tree->
root && !exact_match);
1541 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->
root && !exact_match);
1542 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->
root && !exact_match);
1543 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->
root && !exact_match);
1544 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->
root && !exact_match);
1546 if (!do_register (tree, path1,
TRUE, 1, tree_test_data))
1559 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
1560 _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match);
1561 _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match);
1562 _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match);
1563 _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match);
1564 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->
root && !exact_match);
1565 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->
root && !exact_match);
1566 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->
root && !exact_match);
1567 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->
root && !exact_match);
1569 if (!do_register (tree, path2,
TRUE, 2, tree_test_data))
1581 if (!do_register (tree, path3,
TRUE, 3, tree_test_data))
1594 if (!do_register (tree, path4,
TRUE, 4, tree_test_data))
1607 if (!do_register (tree, path5,
TRUE, 5, tree_test_data))
1620 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->
root && exact_match);
1621 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->
root && exact_match);
1622 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->
root && exact_match);
1623 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->
root && exact_match);
1624 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->
root && exact_match);
1625 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->
root && exact_match);
1626 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->
root && !exact_match);
1627 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->
root && !exact_match);
1628 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->
root && !exact_match);
1630 if (!do_register (tree, path6,
TRUE, 6, tree_test_data))
1643 if (!do_register (tree, path7,
TRUE, 7, tree_test_data))
1656 if (!do_register (tree, path8,
TRUE, 8, tree_test_data))
1669 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->
root && exact_match);
1670 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->
root && exact_match);
1671 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->
root && exact_match);
1672 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->
root && exact_match);
1673 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->
root && exact_match);
1674 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->
root && exact_match);
1675 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->
root && exact_match);
1676 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->
root && exact_match);
1677 _dbus_assert (find_handler (tree, path8, &exact_match) != tree->
root && exact_match);
1682 const char *root[] = {
NULL };
1683 char **child_entries;
1686 _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
1687 if (child_entries !=
NULL)
1689 nb = string_array_length ((
const char**)child_entries);
1694 _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
1695 if (child_entries !=
NULL)
1697 nb = string_array_length ((
const char**)child_entries);
1702 _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
1703 if (child_entries !=
NULL)
1705 nb = string_array_length ((
const char**)child_entries);
1710 _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
1711 if (child_entries !=
NULL)
1713 nb = string_array_length ((
const char**)child_entries);
1735 if (!do_register (tree, path0,
TRUE, 0, tree_test_data))
1737 if (!do_register (tree, path1,
TRUE, 1, tree_test_data))
1739 if (!do_register (tree, path2,
TRUE, 2, tree_test_data))
1741 if (!do_register (tree, path3,
TRUE, 3, tree_test_data))
1743 if (!do_register (tree, path4,
TRUE, 4, tree_test_data))
1745 if (!do_register (tree, path5,
TRUE, 5, tree_test_data))
1747 if (!do_register (tree, path6,
TRUE, 6, tree_test_data))
1749 if (!do_register (tree, path7,
TRUE, 7, tree_test_data))
1751 if (!do_register (tree, path8,
TRUE, 8, tree_test_data))
1881 if (!do_register (tree, path0,
TRUE, 0, tree_test_data))
1883 if (!do_register (tree, path1,
FALSE, 1, tree_test_data))
1885 if (!do_register (tree, path2,
TRUE, 2, tree_test_data))
1887 if (!do_register (tree, path3,
TRUE, 3, tree_test_data))
1889 if (!do_register (tree, path4,
TRUE, 4, tree_test_data))
1891 if (!do_register (tree, path5,
TRUE, 5, tree_test_data))
1893 if (!do_register (tree, path6,
FALSE, 6, tree_test_data))
1895 if (!do_register (tree, path7,
TRUE, 7, tree_test_data))
1897 if (!do_register (tree, path8,
TRUE, 8, tree_test_data))
1904 if (!do_test_dispatch (tree, path0, 0, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1906 if (!do_test_dispatch (tree, path1, 1, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1908 if (!do_test_dispatch (tree, path2, 2, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1910 if (!do_test_dispatch (tree, path3, 3, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1912 if (!do_test_dispatch (tree, path4, 4, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1914 if (!do_test_dispatch (tree, path5, 5, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1916 if (!do_test_dispatch (tree, path6, 6, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1918 if (!do_test_dispatch (tree, path7, 7, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1920 if (!do_test_dispatch (tree, path8, 8, tree_test_data,
_DBUS_N_ELEMENTS (tree_test_data)))
1941 _dbus_object_tree_test (
void)
1943 _dbus_test_oom_handling (
"object tree",
1944 object_tree_test_iteration,