mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-09-24 15:30:04 -05:00
add my signal/callback interface from another project, also update license of utility files to ISC 1.3
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Hugh Bailey <obs.jim@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../util/bmem.h"
|
||||
|
||||
#include "calldata.h"
|
||||
|
||||
/*
|
||||
* Uses a data stack. Probably more complex than it should be, but reduces
|
||||
* cache fetching.
|
||||
*
|
||||
* Stack format is:
|
||||
* [size_t param1_name_size]
|
||||
* [char[] param1_name]
|
||||
* [size_t param1_data_size]
|
||||
* [uint8_t[] param1_data]
|
||||
* [size_t param2_name_size]
|
||||
* [char[] param2_name]
|
||||
* [size_t param2_data_size]
|
||||
* [uint8_t[] param2_data]
|
||||
* [...]
|
||||
*
|
||||
* Strings and string sizes always include the null terminator to allow for
|
||||
* direct referencing.
|
||||
*/
|
||||
|
||||
struct calldata {
|
||||
size_t size; /* size of the stack, in bytes */
|
||||
size_t capacity; /* capacity of the stack, in bytes */
|
||||
uint8_t *stack;
|
||||
};
|
||||
|
||||
static inline void cd_serialize(uint8_t **pos, void *ptr, size_t size)
|
||||
{
|
||||
memcpy(ptr, *pos, size);
|
||||
*pos += size;
|
||||
}
|
||||
|
||||
static inline size_t cd_serialize_size(uint8_t **pos)
|
||||
{
|
||||
size_t size = *(size_t*)*pos;
|
||||
*pos += sizeof(size_t);
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline const char *cd_serialize_string(uint8_t **pos)
|
||||
{
|
||||
size_t size = cd_serialize_size(pos);
|
||||
const char *str = *pos;
|
||||
|
||||
*pos += size;
|
||||
|
||||
return (size != 0) ? str : NULL;
|
||||
}
|
||||
|
||||
static bool cd_getparam(calldata_t data, const char *name,
|
||||
uint8_t **pos)
|
||||
{
|
||||
size_t name_size;
|
||||
|
||||
if (!data->size)
|
||||
return false;
|
||||
|
||||
*pos = data->stack;
|
||||
|
||||
name_size = cd_serialize_size(pos);
|
||||
while (name_size != 0) {
|
||||
const char *param_name = *pos;
|
||||
size_t param_size;
|
||||
|
||||
*pos += name_size;
|
||||
if (strcmp(param_name, name) == 0)
|
||||
return true;
|
||||
|
||||
param_size = cd_serialize_size(pos);
|
||||
*pos += param_size;
|
||||
|
||||
name_size = cd_serialize_size(pos);
|
||||
}
|
||||
|
||||
*pos -= sizeof(size_t);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void cd_copy_string(uint8_t **pos, const char *str, size_t len)
|
||||
{
|
||||
if (!len)
|
||||
len = strlen(str)+1;
|
||||
|
||||
*(size_t*)*pos = len;
|
||||
*pos += sizeof(size_t);
|
||||
memcpy(*pos, str, len);
|
||||
*pos += len;
|
||||
}
|
||||
|
||||
static inline void cd_copy_data(uint8_t **pos, const void *in, size_t size)
|
||||
{
|
||||
*(size_t*)*pos = size;
|
||||
*pos += sizeof(size_t);
|
||||
|
||||
if (size) {
|
||||
memcpy(*pos, in, size);
|
||||
*pos += size;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cd_set_first_param(calldata_t data, const char *name,
|
||||
const void *in, size_t size)
|
||||
{
|
||||
uint8_t *pos;
|
||||
size_t capacity;
|
||||
size_t name_len = strlen(name)+1;
|
||||
|
||||
capacity = sizeof(size_t)*3 + name_len + size;
|
||||
data->size = capacity;
|
||||
|
||||
if (capacity < 128)
|
||||
capacity = 128;
|
||||
|
||||
data->capacity = capacity;
|
||||
data->stack = bmalloc(capacity);
|
||||
|
||||
pos = data->stack;
|
||||
cd_copy_string(&pos, name, name_len);
|
||||
cd_copy_data(&pos, in, size);
|
||||
*(size_t*)pos = 0;
|
||||
}
|
||||
|
||||
static inline void cd_ensure_capacity(calldata_t data, uint8_t **pos,
|
||||
size_t new_size)
|
||||
{
|
||||
size_t offset;
|
||||
size_t new_capacity;
|
||||
|
||||
if (new_size < data->capacity)
|
||||
return;
|
||||
|
||||
offset = *pos - data->stack;
|
||||
|
||||
new_capacity = data->capacity * 2;
|
||||
if (new_capacity < new_size)
|
||||
new_capacity = new_size;
|
||||
|
||||
data->stack = brealloc(data->stack, new_capacity);
|
||||
data->capacity = new_capacity;
|
||||
|
||||
*pos = data->stack + offset;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
calldata_t calldata_create(void)
|
||||
{
|
||||
struct calldata *data = bmalloc(sizeof(struct calldata));
|
||||
memset(data, 0, sizeof(struct calldata));
|
||||
return data;
|
||||
}
|
||||
|
||||
void calldata_destroy(calldata_t data)
|
||||
{
|
||||
if (data) {
|
||||
bfree(data->stack);
|
||||
bfree(data);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
bool calldata_getdata(calldata_t data, const char *name, void *out, size_t size)
|
||||
{
|
||||
uint8_t *pos;
|
||||
size_t data_size;
|
||||
|
||||
if (!name || !*name)
|
||||
return false;
|
||||
|
||||
if (!cd_getparam(data, name, &pos))
|
||||
return false;
|
||||
|
||||
data_size = cd_serialize_size(&pos);
|
||||
if (data_size != size)
|
||||
return false;
|
||||
|
||||
memcpy(out, pos, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
void calldata_setdata(calldata_t data, const char *name, const void *in,
|
||||
size_t size)
|
||||
{
|
||||
uint8_t *pos;
|
||||
|
||||
if (!name || !*name)
|
||||
return;
|
||||
|
||||
if (!data->stack) {
|
||||
cd_set_first_param(data, name, in, size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cd_getparam(data, name, &pos)) {
|
||||
size_t cur_size = *(size_t*)pos;
|
||||
|
||||
if (cur_size < size) {
|
||||
size_t offset = size - cur_size;
|
||||
size_t bytes = data->size;
|
||||
|
||||
cd_ensure_capacity(data, &pos, bytes + offset);
|
||||
memmove(pos+offset, pos, bytes - (pos - data->stack));
|
||||
data->size += offset;
|
||||
|
||||
} else if (cur_size > size) {
|
||||
size_t offset = cur_size - size;
|
||||
size_t bytes = data->size - offset;
|
||||
|
||||
memmove(pos, pos+offset, bytes - (pos - data->stack));
|
||||
data->size -= offset;
|
||||
}
|
||||
|
||||
cd_copy_data(&pos, in, size);
|
||||
|
||||
} else {
|
||||
size_t name_len = strlen(name)+1;
|
||||
size_t offset = name_len + size + sizeof(size_t)*2;
|
||||
cd_ensure_capacity(data, &pos, data->size + offset);
|
||||
data->size += offset;
|
||||
|
||||
cd_copy_string(&pos, name, 0);
|
||||
cd_copy_data(&pos, in, size);
|
||||
*(size_t*)pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void calldata_clear(calldata_t data)
|
||||
{
|
||||
if (data->size) {
|
||||
data->size = sizeof(size_t);
|
||||
*(size_t*)data->stack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool calldata_getstring(calldata_t data, const char *name, const char **str)
|
||||
{
|
||||
uint8_t *pos;
|
||||
if (!name || !*name)
|
||||
return false;
|
||||
|
||||
if (!cd_getparam(data, name, &pos))
|
||||
return false;
|
||||
|
||||
*str = cd_serialize_string(&pos);
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user