2019-04-05 12:44:21 +00:00
|
|
|
// Copyright 2019, Collabora, Ltd.
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
|
|
/*!
|
|
|
|
* @file
|
|
|
|
* @brief Holds path related functions.
|
|
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
|
|
|
* @ingroup oxr_main
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "math/m_api.h"
|
|
|
|
#include "util/u_misc.h"
|
|
|
|
|
|
|
|
#include "oxr_objects.h"
|
|
|
|
#include "oxr_logger.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Internal representation of a path, item follows this struct in memory and
|
|
|
|
* that in turn is followed by the string.
|
|
|
|
*
|
|
|
|
* @ingroup oxr_main
|
|
|
|
*/
|
|
|
|
struct oxr_path
|
|
|
|
{
|
|
|
|
uint64_t debug;
|
2020-05-27 20:04:58 +00:00
|
|
|
XrPath id;
|
2019-04-05 12:44:21 +00:00
|
|
|
void *attached;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Helpers
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline XrPath
|
|
|
|
to_xr_path(struct oxr_path *path)
|
|
|
|
{
|
2020-05-27 20:04:58 +00:00
|
|
|
return path->id;
|
2019-04-05 12:44:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct u_hashset_item *
|
|
|
|
get_item(struct oxr_path *path)
|
|
|
|
{
|
|
|
|
return (struct u_hashset_item *)&path[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct oxr_path *
|
|
|
|
from_item(struct u_hashset_item *item)
|
|
|
|
{
|
|
|
|
return &((struct oxr_path *)item)[-1];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Static functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-05-27 20:04:58 +00:00
|
|
|
static XrResult
|
|
|
|
oxr_ensure_array_length(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
XrPath *out_id)
|
|
|
|
{
|
|
|
|
size_t num = inst->path_num + 1;
|
|
|
|
|
|
|
|
if (num < inst->path_array_length) {
|
|
|
|
*out_id = inst->path_num++;
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t new_size = inst->path_array_length;
|
|
|
|
while (new_size < num) {
|
|
|
|
new_size += 64;
|
|
|
|
}
|
|
|
|
|
|
|
|
U_ARRAY_REALLOC_OR_FREE(inst->path_array, struct oxr_path *, new_size);
|
|
|
|
inst->path_array_length = new_size;
|
|
|
|
|
|
|
|
*out_id = inst->path_num++;
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-04-05 12:44:21 +00:00
|
|
|
static XrResult
|
|
|
|
oxr_allocate_path(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
const char *str,
|
|
|
|
size_t length,
|
|
|
|
struct oxr_path **out_path)
|
|
|
|
{
|
|
|
|
struct u_hashset_item *item = NULL;
|
|
|
|
struct oxr_path *path = NULL;
|
|
|
|
size_t size = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
size += sizeof(struct oxr_path); // Main path object.
|
|
|
|
size += sizeof(struct u_hashset_item); // Embedded hashset item.
|
|
|
|
size += length; // String.
|
|
|
|
size += 1; // Null terminate it.
|
|
|
|
|
|
|
|
// Now allocate and setup the path.
|
|
|
|
path = U_CALLOC_WITH_CAST(struct oxr_path, size);
|
|
|
|
if (path == NULL) {
|
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
|
|
|
|
"Failed to allocate path");
|
|
|
|
}
|
|
|
|
path->debug = OXR_XR_DEBUG_PATH;
|
|
|
|
|
|
|
|
// Setup the item.
|
|
|
|
item = get_item(path);
|
|
|
|
item->hash = math_hash_string(str, length);
|
|
|
|
item->length = length;
|
|
|
|
|
|
|
|
// Yes a const cast! D:
|
|
|
|
char *store = (char *)item->c_str;
|
|
|
|
for (size_t i = 0; i < length; i++) {
|
|
|
|
store[i] = str[i];
|
|
|
|
}
|
|
|
|
store[length] = '\0';
|
|
|
|
|
|
|
|
// Insert and return.
|
|
|
|
ret = u_hashset_insert_item(inst->path_store, item);
|
|
|
|
if (ret) {
|
|
|
|
free(path);
|
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
|
|
|
|
"Failed to insert item");
|
|
|
|
}
|
|
|
|
|
2020-05-27 20:04:58 +00:00
|
|
|
oxr_ensure_array_length(log, inst, &path->id);
|
|
|
|
inst->path_array[path->id] = path;
|
|
|
|
|
2019-04-05 12:44:21 +00:00
|
|
|
*out_path = path;
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-05-27 20:04:58 +00:00
|
|
|
struct oxr_path *
|
|
|
|
get_path_or_null(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
XrPath xr_path)
|
|
|
|
{
|
|
|
|
if (xr_path >= inst->path_array_length) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return inst->path_array[xr_path];
|
|
|
|
}
|
2019-04-05 12:44:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* "Exported" functions.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
void *
|
|
|
|
oxr_path_get_attached(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
XrPath xr_path)
|
|
|
|
{
|
2020-05-27 20:04:58 +00:00
|
|
|
struct oxr_path *path = get_path_or_null(log, inst, xr_path);
|
|
|
|
if (path == NULL) {
|
2019-04-05 12:44:21 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-27 20:04:58 +00:00
|
|
|
return path->attached;
|
2019-04-05 12:44:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
XrResult
|
|
|
|
oxr_path_get_or_create(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
const char *str,
|
|
|
|
size_t length,
|
|
|
|
XrPath *out_path)
|
|
|
|
{
|
|
|
|
struct u_hashset_item *item;
|
2019-07-24 23:52:07 +00:00
|
|
|
struct oxr_path *path = NULL;
|
2019-04-05 12:44:21 +00:00
|
|
|
XrResult ret;
|
|
|
|
int h_ret;
|
|
|
|
|
|
|
|
// Look it up the instance path store.
|
|
|
|
h_ret = u_hashset_find_str(inst->path_store, str, length, &item);
|
|
|
|
if (h_ret == 0) {
|
|
|
|
*out_path = to_xr_path(from_item(item));
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the path since it was not found.
|
|
|
|
ret = oxr_allocate_path(log, inst, str, length, &path);
|
|
|
|
if (ret != XR_SUCCESS) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_path = to_xr_path(path);
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
XrResult
|
|
|
|
oxr_path_only_get(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
const char *str,
|
|
|
|
size_t length,
|
|
|
|
XrPath *out_path)
|
|
|
|
{
|
|
|
|
struct u_hashset_item *item;
|
|
|
|
int h_ret;
|
|
|
|
|
|
|
|
// Look it up the instance path store.
|
|
|
|
h_ret = u_hashset_find_str(inst->path_store, str, length, &item);
|
|
|
|
if (h_ret == 0) {
|
|
|
|
*out_path = to_xr_path(from_item(item));
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out_path = XR_NULL_PATH;
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
XrResult
|
|
|
|
oxr_path_get_string(struct oxr_logger *log,
|
|
|
|
struct oxr_instance *inst,
|
|
|
|
XrPath xr_path,
|
|
|
|
const char **out_str,
|
|
|
|
size_t *out_length)
|
|
|
|
{
|
2020-05-27 20:04:58 +00:00
|
|
|
struct oxr_path *path = get_path_or_null(log, inst, xr_path);
|
|
|
|
if (path == NULL) {
|
|
|
|
return XR_ERROR_PATH_INVALID;
|
|
|
|
}
|
2019-04-05 12:44:21 +00:00
|
|
|
|
|
|
|
*out_str = get_item(path)->c_str;
|
|
|
|
*out_length = get_item(path)->length;
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
destroy_callback(struct u_hashset_item *item, void *priv)
|
|
|
|
{
|
|
|
|
struct oxr_path *path = from_item(item);
|
|
|
|
|
|
|
|
free(path);
|
|
|
|
}
|
|
|
|
|
2020-05-27 20:04:58 +00:00
|
|
|
XrResult
|
|
|
|
oxr_path_init(struct oxr_logger *log, struct oxr_instance *inst)
|
|
|
|
{
|
|
|
|
int h_ret = u_hashset_create(&inst->path_store);
|
|
|
|
if (h_ret != 0) {
|
|
|
|
return oxr_error(log, XR_ERROR_RUNTIME_FAILURE,
|
|
|
|
"Failed to create hashset");
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t new_size = 64;
|
|
|
|
U_ARRAY_REALLOC_OR_FREE(inst->path_array, struct oxr_path *, new_size);
|
|
|
|
inst->path_array_length = new_size;
|
|
|
|
inst->path_num = 1; // Reserve space for XR_NULL_PATH
|
|
|
|
|
|
|
|
return XR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-04-05 12:44:21 +00:00
|
|
|
void
|
2020-05-27 20:04:58 +00:00
|
|
|
oxr_path_destroy(struct oxr_logger *log, struct oxr_instance *inst)
|
2019-04-05 12:44:21 +00:00
|
|
|
{
|
2020-05-27 20:04:58 +00:00
|
|
|
if (inst->path_array != NULL) {
|
|
|
|
free(inst->path_array);
|
|
|
|
}
|
|
|
|
|
|
|
|
inst->path_array = NULL;
|
|
|
|
inst->path_num = 0;
|
|
|
|
inst->path_array_length = 0;
|
|
|
|
|
|
|
|
if (inst->path_store == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-05 12:44:21 +00:00
|
|
|
u_hashset_clear_and_call_for_each(inst->path_store, destroy_callback,
|
|
|
|
inst);
|
2020-05-27 20:04:58 +00:00
|
|
|
u_hashset_destroy(&inst->path_store);
|
2019-04-05 12:44:21 +00:00
|
|
|
}
|