monado/src/xrt/state_trackers/oxr/oxr_path.c

220 lines
4.5 KiB
C
Raw Normal View History

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;
void *attached;
};
/*
*
* Helpers
*
*/
static inline struct oxr_path *
oxr_path(XrPath path)
{
return XRT_CAST_OXR_HANDLE_TO_PTR(struct oxr_path *, path);
2019-04-05 12:44:21 +00:00
}
static inline XrPath
to_xr_path(struct oxr_path *path)
{
return XRT_CAST_PTR_TO_OXR_HANDLE(XrPath, path);
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.
*
*/
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");
}
*out_path = path;
return XR_SUCCESS;
}
/*
*
* "Exported" functions.
*
*/
void *
oxr_path_get_attached(struct oxr_logger *log,
struct oxr_instance *inst,
XrPath xr_path)
{
if (xr_path == XR_NULL_PATH) {
return NULL;
}
return oxr_path(xr_path)->attached;
}
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;
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)
{
struct oxr_path *path = oxr_path(xr_path);
*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);
}
void
2019-04-12 10:46:59 +00:00
oxr_path_destroy_all(struct oxr_logger *log, struct oxr_instance *inst)
2019-04-05 12:44:21 +00:00
{
u_hashset_clear_and_call_for_each(inst->path_store, destroy_callback,
inst);
}