static int foreach_property(const uint32_t off, void (*propfn)(const prop_info *pi, void *cookie), void *cookie) { prop_bt *trie = reinterpret_cast<prop_bt*>(to_prop_obj(off)); if (!trie) return -1; if (trie->left) { const int err = foreach_property(trie->left, propfn, cookie); if (err < 0) return -1; } if (trie->prop) { prop_info *info = reinterpret_cast<prop_info*>(to_prop_obj(trie->prop)); if (!info) return -1; propfn(info, cookie); } if (trie->children) { const int err = foreach_property(trie->children, propfn, cookie); if (err < 0) return -1; } if (trie->right) { const int err = foreach_property(trie->right, propfn, cookie); if (err < 0) return -1; } return 0; }
static const prop_info *find_property(prop_bt *const trie, const char *name, uint8_t namelen, const char *value, uint8_t valuelen, bool alloc_if_needed) { if (!trie) return NULL; const char *remaining_name = name; prop_bt* current = trie; while (true) { const char *sep = strchr(remaining_name, '.'); const bool want_subtree = (sep != NULL); const uint8_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name); if (!substr_size) { return NULL; } prop_bt* root = NULL; if (current->children) { root = reinterpret_cast<prop_bt*>(to_prop_obj(current->children)); } else if (alloc_if_needed) { uint32_t new_bt_offset; root = new_prop_bt(remaining_name, substr_size, &new_bt_offset); if (root) { current->children = new_bt_offset; } } if (!root) { return NULL; } current = find_prop_bt(root, remaining_name, substr_size, alloc_if_needed); if (!current) { return NULL; } if (!want_subtree) break; remaining_name = sep + 1; } if (current->prop) { return reinterpret_cast<prop_info*>(to_prop_obj(current->prop)); } else if (alloc_if_needed) { uint32_t new_info_offset; prop_info* new_info = new_prop_info(name, namelen, value, valuelen, &new_info_offset); if (new_info) { current->prop = new_info_offset; } return new_info; } else { return NULL; } }
static prop_bt *find_prop_bt(prop_bt *const bt, const char *name, uint8_t namelen, bool alloc_if_needed) { prop_bt* current = bt; while (true) { if (!current) { return NULL; } const int ret = cmp_prop_name(name, namelen, current->name, current->namelen); if (ret == 0) { return current; } if (ret < 0) { if (current->left) { current = reinterpret_cast<prop_bt*>(to_prop_obj(current->left)); } else { if (!alloc_if_needed) { return NULL; } // Note that there isn't a race condition here. "clients" never // reach this code-path since It's only the (single threaded) server // that allocates new nodes. Though "bt->left" is volatile, it can't // have changed since the last value was last read. uint32_t new_offset = 0; prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset); if (new_bt) { current->left = new_offset; } return new_bt; } } else { if (current->right) { current = reinterpret_cast<prop_bt*>(to_prop_obj(current->right)); } else { if (!alloc_if_needed) { return NULL; } uint32_t new_offset; prop_bt* new_bt = new_prop_bt(name, namelen, &new_offset); if (new_bt) { current->right = new_offset; } return new_bt; } } } }
static prop_bt *root_node() { return reinterpret_cast<prop_bt*>(to_prop_obj(0)); }
inline prop_bt *prop_area::root_node() { return reinterpret_cast<prop_bt*>(to_prop_obj(0)); }
inline prop_info *prop_area::to_prop_info(atomic_uint_least32_t* off_p) { uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume); return reinterpret_cast<prop_info*>(to_prop_obj(off)); }