mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-15 20:30:00 +01:00
2814 lines
64 KiB
C
2814 lines
64 KiB
C
/*
|
|
Copyright (c) 2004-2005 N.Elburg <nwelburg@gmail.com>
|
|
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
3. The name of the author may not be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/** \defgroup VeVo Veejay Video Objects
|
|
*
|
|
* VeVo provides a data model for handling dynamic
|
|
* objects in runtime.
|
|
*
|
|
* Features:
|
|
* -# Efficient object caching with reference counting
|
|
* -# Generic per object properties with set/get functions
|
|
* -# Fast hashing of keys
|
|
*
|
|
* To distinguish between objects as in object oriented programming,
|
|
* Ports are introduced. A Port is a container of properties.
|
|
*
|
|
* A property is a tupple of a value and an unique key.
|
|
* A key is a human friendly name for a Property. Internally a list
|
|
* of mnenomics is kept to translate the human friendly name into a numeric value
|
|
* that uniquely identifies an object.
|
|
*
|
|
* Types of values:
|
|
* -# int32_t VEVO_ATOM_TYPE_INT
|
|
* -# char* VEVO_ATOM_TYPE_STRING
|
|
* -# gchar* VEVO_ATOM_TYPE_UTF8STRING
|
|
* -# void* VEVO_ATOM_TYPE_VOIDPTR
|
|
* -# void* VEVO_ATOM_TYPE_PORTPTR
|
|
* -# int32_t VEVO_ATOM_TYPE_BOOLEAN
|
|
* -# uint64_t VEVO_ATOM_TYPE_UINT64
|
|
*
|
|
*
|
|
*
|
|
* Values of type STRING must always be NULL-terminated, vevo creates
|
|
* a dynamic copy on both set and get functions.
|
|
*
|
|
* Values of type VOIDPTR must always be freed by caller.
|
|
*
|
|
* Values of type PORTPTR will be cleaned up by vevo when no longer needed.
|
|
*
|
|
* Depending on the type of port that is constructed
|
|
* -# the port uses a linked list of objects
|
|
* -# the port uses a hash table of objects
|
|
* -# the port's type is stored as "type"
|
|
* -# the port's type is not stored (anonymous port)
|
|
*
|
|
* A Port has no limit on the amounts of properties it can hold.
|
|
* Vevo can recursivly walk all ports and free them, except for
|
|
* those Properties that are of the VEVO_ATOM_TYPE_VOIDPTR
|
|
*
|
|
* Vevo will complain about:
|
|
* -# Ports that have never been freed
|
|
* -# Ports that have not been allocated by vevo
|
|
* -# Ports that have already been freed
|
|
*
|
|
* This library is not complete, it contains some loose ends:
|
|
* - sscanf/ printf
|
|
* - vevo_num_properties
|
|
*
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <libvevo/vevo.h>
|
|
|
|
#include <libvevo/libvevo.h>
|
|
#include <libhash/hash.h>
|
|
#include <libvjmem/vjmem.h>
|
|
#include <libvjmsg/vj-msg.h>
|
|
//#include <glib-2.0/glib.h> //@ for g_locale_to_utf8 and g_locale_from_utf8
|
|
|
|
#include <libvevo/pool.h>
|
|
#define PORT_TYPE_PLUGIN_INFO 1
|
|
#define PORT_TYPE_FILTER_CLASS 2
|
|
#define PORT_TYPE_FILTER_INSTANCE 3
|
|
#define PORT_TYPE_CHANNEL_TEMPLATE 4
|
|
#define PORT_TYPE_PARAMETER_TEMPLATE 5
|
|
#define PORT_TYPE_CHANNEL 6
|
|
#define PORT_TYPE_PARAMETER 7
|
|
#define PORT_TYPE_GUI 8
|
|
|
|
//
|
|
|
|
//! \typedef atom_t
|
|
/*! \brief atom
|
|
*
|
|
* the atom_t structure
|
|
*/
|
|
|
|
|
|
#ifdef ARCH_X86_64
|
|
typedef uint64_t ukey_t;
|
|
#else
|
|
typedef uint32_t ukey_t;
|
|
#endif
|
|
|
|
typedef void (*vevo_set_func)(void *ctx, int32_t type, int32_t value );
|
|
typedef int (*vevo_get_func)(void *ctx );
|
|
|
|
typedef struct {
|
|
int type;
|
|
void *value;
|
|
int (*get_func)();
|
|
void(*set_func)();
|
|
size_t size;
|
|
} atom_t;
|
|
|
|
//! \typedef vevo_storage_t
|
|
/*! \brief atom storage
|
|
*
|
|
*
|
|
* the vevo_storage_t structure holds one or more elements
|
|
* and some bookkeeping information
|
|
*/
|
|
typedef struct {
|
|
int atom_type; /*!< atom type */
|
|
union { /*! \union elements one or more atoms */
|
|
atom_t *atom;
|
|
atom_t **array;
|
|
} elements;
|
|
int num_elements; /*!< number of atoms */
|
|
int flags; /*!< special flags */
|
|
int softlink; /*! < protected, use to indicate soft link */
|
|
} vevo_storage_t;
|
|
|
|
//! \typedef vevo_property_t
|
|
/*! \brief tupple of key | object storage
|
|
*
|
|
*
|
|
* the vevo_property_t structure binds a key to a vevo_storage_t structure
|
|
*/
|
|
typedef struct {
|
|
vevo_storage_t *st;
|
|
ukey_t key;
|
|
void *next;
|
|
} vevo_property_t;
|
|
|
|
//! \typedef port_index_t
|
|
/*! \brief mnemonics of key | hash value pairs
|
|
*
|
|
*
|
|
* the port_index_t keeps a mnemonic of key to hash code
|
|
*/
|
|
typedef struct {
|
|
const char *key;
|
|
ukey_t hash_code; /* vevo uses a integer representation of key, eliminates strcmp */
|
|
void *next;
|
|
} port_index_t;
|
|
|
|
//! \typedef __vevo_port_t
|
|
/*! \brief top level container
|
|
*
|
|
*
|
|
* the __vevo_port_t is the top level structure
|
|
*/
|
|
typedef struct {
|
|
hash_t *table; /*!< hashtable to store pairs of key | value */
|
|
vevo_property_t *list; /*!< linked list to store pairs of key | value */
|
|
port_index_t *index; /*!< mnemonic table of key to hashcode */
|
|
void *pool; /*!< pointer to pool_t object caching */
|
|
} __vevo_port_t;
|
|
|
|
|
|
//! \var port_ref_ Book keeping of allocated and freed ports
|
|
static size_t atom_sizes_[100];
|
|
|
|
static char *vevo_scan_token_( const char *s );
|
|
static const char *vevo_split_token_q( const char *s, const char delim, char *buf, int buf_len );
|
|
|
|
|
|
static const char *vevo_split_token_( const char *s, const char delim, char *buf, int buf_len );
|
|
|
|
|
|
//! Construct a new vevo_property_t
|
|
/*!
|
|
\param port port
|
|
\param hash_key hash value
|
|
\param stor vevo_storage_t
|
|
*/
|
|
static vevo_property_t *prop_node_new(__vevo_port_t *port, ukey_t hash_key,
|
|
vevo_storage_t * stor)
|
|
{
|
|
vevo_property_t *p =
|
|
(vevo_property_t*) vevo_pool_alloc_property( vevo_property_t, port->pool );
|
|
// (vevo_property_t *) vevo_malloc(sizeof(vevo_property_t));
|
|
p->st = stor;
|
|
p->key = hash_key;
|
|
p->next = NULL;
|
|
return p;
|
|
}
|
|
|
|
//! Destroy a property
|
|
/*!
|
|
\param port port
|
|
\param p property to free
|
|
*/
|
|
static void prop_node_free(__vevo_port_t *port,vevo_property_t * p)
|
|
{
|
|
if (p) {
|
|
//free(p);
|
|
p->key = 0;
|
|
vevo_pool_free_property( port->pool, p );
|
|
}
|
|
p = NULL;
|
|
}
|
|
//! Append a property to the linked list of properties
|
|
/*!
|
|
\param p port
|
|
\param key hash value
|
|
\param t vevo_storage_t
|
|
*/
|
|
static vevo_property_t *prop_node_append(__vevo_port_t *port, ukey_t key,
|
|
vevo_storage_t * t)
|
|
{
|
|
vevo_property_t *node = prop_node_new(port,key, t);
|
|
vevo_property_t *next;
|
|
vevo_property_t *list = port->list;
|
|
if (list == NULL)
|
|
port->list = node;
|
|
else {
|
|
while (list != NULL) {
|
|
next = list->next;
|
|
if (next == NULL) {
|
|
list->next = node;
|
|
return node;
|
|
}
|
|
list = next;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
//! Get a property from a port
|
|
/*!
|
|
\param port
|
|
\param key hash value
|
|
*/
|
|
static vevo_property_t *prop_node_get(__vevo_port_t *port, ukey_t key)
|
|
{
|
|
vevo_property_t *l = port->list;
|
|
while (l != NULL) {
|
|
if (key == l->key)
|
|
return l;
|
|
l = l->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//! Construct a new mnemonic
|
|
/*!
|
|
\param port port
|
|
\param key name of property
|
|
\param hash_key calculated hash value
|
|
\return port_index_t new mmemonic
|
|
*/
|
|
static port_index_t *port_node_new(__vevo_port_t *port,const char *key, ukey_t hash_key)
|
|
{
|
|
port_index_t *i = (port_index_t *) vevo_pool_alloc_node(port_index_t, port->pool );
|
|
i->key = vj_strdup(key);
|
|
i->hash_code = hash_key;
|
|
i->next = NULL;
|
|
return i;
|
|
}
|
|
|
|
//! Destroy a mnemonic from the list of key | hash value pairs
|
|
/*!
|
|
\param port port
|
|
\param node mnemonic to destroy
|
|
*/
|
|
static void port_node_free(__vevo_port_t *port,port_index_t * node)
|
|
{
|
|
if(node->key) free((void*)node->key);
|
|
vevo_pool_free_node( port->pool,(void*)node );
|
|
}
|
|
|
|
//! Add a mnemonic to the list of key | hash value pairs
|
|
/*!
|
|
\param p port
|
|
\param key name of property
|
|
\param hash_key calculated hash value
|
|
*/
|
|
static void port_node_append(__vevo_port_t * port, const char *key,ukey_t hash_key)
|
|
{
|
|
port_index_t *node = port_node_new(port,key, hash_key);
|
|
port_index_t *next = NULL;
|
|
port_index_t *list = port->index;
|
|
if (list == NULL)
|
|
port->index = node;
|
|
else {
|
|
while (list != NULL) {
|
|
next = list->next;
|
|
if (next == NULL) {
|
|
list->next = node;
|
|
break;
|
|
}
|
|
list = next;
|
|
}
|
|
}
|
|
}
|
|
|
|
#define PROPERTY_KEY_SIZE 128
|
|
//! \define property_exists Check if a property exists
|
|
//#define property_exists( port, key ) hash_lookup( (hash_t*) port->table, (const void*) key )
|
|
static inline hnode_t *property_exists( __vevo_port_t *port, ukey_t key )
|
|
{
|
|
return (hnode_t*) hash_lookup( (hash_t*) port->table,(const void*) key );
|
|
}
|
|
|
|
//! \define atom_store__ store atom
|
|
#define atom_store__(value) {\
|
|
for (i = 0; i < d->num_elements; i++)\
|
|
d->elements.array[i] = vevo_put_atom(port, &value[i], v ); }
|
|
|
|
//! Construct a new vevo_storage_t object
|
|
/*!
|
|
\param port port
|
|
\return vevo_storage_t a new vevo_storage_t object
|
|
*/
|
|
static vevo_storage_t *vevo_new_storage(__vevo_port_t *port );
|
|
|
|
static void
|
|
storage_put_atom_value(__vevo_port_t * port, void *src, int n,
|
|
vevo_storage_t * d, int v);
|
|
|
|
//! Calculate a hash value from a given string
|
|
/*!
|
|
\param str string
|
|
\return calculated hash value
|
|
*/
|
|
static inline ukey_t hash_key_code( const char *str )
|
|
{
|
|
ukey_t hash = 5381;
|
|
int c;
|
|
while( (c = (int) *str++) != 0)
|
|
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
|
|
|
return hash;
|
|
}
|
|
|
|
//! Flag a property as soft referenced. Use to avoid freeing a linked pointer.
|
|
/*!
|
|
\param p port
|
|
\param key property to soft reference
|
|
\return error code
|
|
*/
|
|
int vevo_property_soft_reference(vevo_port_t * p, const char *key)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
node->st->softlink = 1;
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
stor->softlink = 1;
|
|
hnode_put( node, (void*) hash_key );
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
}
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
int vevo_property_protect( vevo_port_t *p, const char *key )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
node->st->flags |= VEVO_PROPERTY_PROTECTED;
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
stor->flags |= VEVO_PROPERTY_PROTECTED;
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
}
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
int vevo_property_softref( vevo_port_t *p, const char *key )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
node->st->flags |= VEVO_PROPERTY_SOFTREF;
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
stor->flags |= VEVO_PROPERTY_SOFTREF;
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
}
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
|
|
static int vevo_property_exists( vevo_port_t *p, const char *key)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL)
|
|
return 1;
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//! Copy a value from an atom to an address
|
|
/*!
|
|
\param t vevo_storage_t source
|
|
\param idx element at
|
|
\param dst destination address
|
|
\return error code
|
|
*/
|
|
static int atom_get_value(vevo_storage_t * t, int idx, void *dst)
|
|
{
|
|
atom_t *atom = NULL;
|
|
if (t->num_elements == 1 && idx == 0)
|
|
{
|
|
atom = t->elements.atom;
|
|
}
|
|
|
|
if (t->num_elements > 1 && idx >= 0 && idx < t->num_elements)
|
|
{
|
|
atom = t->elements.array[idx];
|
|
}
|
|
|
|
if( t->num_elements == 0 && idx == 0 )
|
|
{
|
|
return VEVO_ERROR_PROPERTY_EMPTY;
|
|
}
|
|
|
|
|
|
if (!atom)
|
|
return VEVO_ERROR_NOSUCH_ELEMENT;
|
|
|
|
if (atom->size <= 0)
|
|
return VEVO_NO_ERROR;
|
|
// return VEVO_ERROR_PROPERTY_EMPTY;
|
|
|
|
if( dst == NULL )
|
|
return VEVO_NO_ERROR;
|
|
|
|
if( t->atom_type == VEVO_ATOM_TYPE_FUNCPTR )
|
|
return VEVO_NO_ERROR;
|
|
|
|
if( t->atom_type != VEVO_ATOM_TYPE_STRING ) {
|
|
veejay_memcpy(dst,atom->value,atom->size);
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
else {
|
|
char **ptr = (char **) dst;
|
|
char *p = *ptr;
|
|
veejay_memcpy(p, atom->value, atom->size);
|
|
}
|
|
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
//! Get the byte size of an atom
|
|
/*!
|
|
\param atom_type atom type
|
|
\return byte size
|
|
*/
|
|
static size_t vevo_atom_size(int atom_type)
|
|
{
|
|
return atom_sizes_[atom_type];
|
|
}
|
|
|
|
//! Construct a new Atom
|
|
/*!
|
|
\param port port
|
|
\param atom_type type of atom to construct
|
|
\param atom_size byte size of atom
|
|
\return atom_t new atom
|
|
*/
|
|
|
|
static atom_t *vevo_new_atom(__vevo_port_t * port, int atom_type,
|
|
size_t atom_size)
|
|
{
|
|
atom_t *atom = (atom_t *) vevo_pool_alloc_atom( atom_t , port->pool );
|
|
atom->size = atom_size;
|
|
atom->type = atom_type;
|
|
|
|
if( atom_size == 0 )
|
|
return atom;
|
|
|
|
if(atom_type == VEVO_ATOM_TYPE_STRING || atom_type == VEVO_ATOM_TYPE_UTF8STRING )
|
|
{
|
|
atom->value = (atom_size > 0 ?(void*)vj_malloc(atom_size):NULL);
|
|
//@ TODO: strings do not come from pool
|
|
}else
|
|
{ if(atom_type == VEVO_ATOM_TYPE_DOUBLE ) {
|
|
atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_dbl(double,port->pool ): NULL);
|
|
} else if( atom_type == VEVO_ATOM_TYPE_VOIDPTR || atom_type == VEVO_ATOM_TYPE_PORTPTR ) {
|
|
atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_ptr(void*,port->pool ): NULL );
|
|
} else if( atom_type == VEVO_ATOM_TYPE_UINT64 ) {
|
|
atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_64b(uint64_t,port->pool) : NULL );
|
|
} else {
|
|
atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_int(int32_t, port->pool ): NULL );
|
|
}
|
|
}
|
|
return atom;
|
|
}
|
|
|
|
//! Destroy an atom
|
|
/*!
|
|
\param port port
|
|
\param atom atom_t to destroy
|
|
*/
|
|
static void vevo_free_atom(__vevo_port_t *port,atom_t * atom)
|
|
{
|
|
if (atom) {
|
|
if(atom->value) {
|
|
switch( atom->type )
|
|
{
|
|
case VEVO_ATOM_TYPE_VOIDPTR:
|
|
case VEVO_ATOM_TYPE_PORTPTR:
|
|
vevo_pool_free_ptr( port->pool, atom->value );
|
|
break;
|
|
case VEVO_ATOM_TYPE_INT:
|
|
case VEVO_ATOM_TYPE_BOOL:
|
|
vevo_pool_free_int( port->pool, atom->value );
|
|
break;
|
|
case VEVO_ATOM_TYPE_DOUBLE:
|
|
vevo_pool_free_dbl( port->pool,atom->value );
|
|
break;
|
|
case VEVO_ATOM_TYPE_UINT64:
|
|
vevo_pool_free_64b( port->pool,atom->value );
|
|
break;
|
|
case VEVO_ATOM_TYPE_STRING:
|
|
case VEVO_ATOM_TYPE_UTF8STRING:
|
|
free( atom->value );
|
|
break;
|
|
}
|
|
atom->value = NULL;
|
|
}
|
|
vevo_pool_free_atom( port->pool, atom );
|
|
atom = NULL;
|
|
}
|
|
}
|
|
|
|
//! Copy a value from address into a new Atom
|
|
/*!
|
|
\param port port
|
|
\param dst destination address
|
|
\param atom_type type of atom
|
|
*/
|
|
static atom_t *vevo_put_atom(__vevo_port_t * port, void *dst, int atom_type)
|
|
{
|
|
atom_t *atom = NULL;
|
|
if (atom_type == VEVO_ATOM_TYPE_STRING || atom_type == VEVO_ATOM_TYPE_UTF8STRING) {
|
|
char **s = (char **) dst;
|
|
char *data = (char*) *s;
|
|
size_t atom_size = (dst == NULL || data == NULL ? 0 : strlen(data) + 1);
|
|
atom = vevo_new_atom(port, atom_type, atom_size);
|
|
if (atom_size > 0) {
|
|
veejay_memcpy(atom->value, data, atom_size);
|
|
}
|
|
} else {
|
|
size_t atom_size = vevo_atom_size(atom_type);
|
|
atom = vevo_new_atom(port, atom_type, atom_size);
|
|
if (!atom)
|
|
return NULL;
|
|
veejay_memcpy(atom->value, dst, atom_size);
|
|
}
|
|
return atom;
|
|
}
|
|
|
|
|
|
//! Copy N values from address into a new Atom
|
|
/*!
|
|
\param port port
|
|
\param src source address
|
|
\param n number of elements
|
|
\param d vevo_storage_t
|
|
\param v type of atom
|
|
*/
|
|
|
|
static void
|
|
storage_put_atom_value(__vevo_port_t * port, void *src, int n,
|
|
vevo_storage_t * d, int v)
|
|
{
|
|
int i;
|
|
|
|
//@ overwrite
|
|
if (d->num_elements == 0 || d->num_elements == 1) {
|
|
//@ single atoms
|
|
if (d->elements.atom)
|
|
vevo_free_atom(port,d->elements.atom);
|
|
} else if (d->num_elements > 1) {
|
|
if (d->elements.array) {
|
|
for (i = 0; i < d->num_elements; i++)
|
|
{
|
|
vevo_free_atom(port,d->elements.array[i]);
|
|
}
|
|
free(d->elements.array);
|
|
}
|
|
}
|
|
|
|
d->atom_type = v;
|
|
d->num_elements = n;
|
|
|
|
switch (n) {
|
|
case 0:
|
|
d->elements.atom = vevo_new_atom(port, v, vevo_atom_size(v));
|
|
break;
|
|
case 1:
|
|
d->elements.atom = vevo_put_atom(port, src, v);
|
|
break;
|
|
default:
|
|
d->elements.array = (atom_t **) vj_malloc(sizeof(atom_t *) * n);
|
|
if (d->atom_type == VEVO_ATOM_TYPE_DOUBLE) {
|
|
double *value = (double *) src;
|
|
atom_store__(value);
|
|
} else {
|
|
if (d->atom_type == VEVO_ATOM_TYPE_INT|| d->atom_type == VEVO_ATOM_TYPE_BOOL) {
|
|
int32_t *value = (int32_t *) src;
|
|
atom_store__(value);
|
|
} else if(d->atom_type == VEVO_ATOM_TYPE_UINT64) {
|
|
uint64_t *value = (uint64_t*) src;
|
|
atom_store__(value);
|
|
} else {
|
|
void **value = (void **) src;
|
|
atom_store__(value);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
storage_put_atom_func(__vevo_port_t * port, void (*set_func)(),int (*get_func)(), vevo_storage_t * d, int v)
|
|
{
|
|
if( set_func == NULL && get_func == NULL )
|
|
{
|
|
vevo_free_atom(port,d->elements.atom);
|
|
d->elements.atom = NULL;
|
|
}
|
|
|
|
d->atom_type = v;
|
|
d->num_elements = 1;
|
|
d->elements.atom = vevo_new_atom(port, v, 0);
|
|
|
|
d->elements.atom->set_func = set_func;
|
|
d->elements.atom->get_func = get_func;
|
|
|
|
//memcpy(set_func,d->elements.atom->set_func, sizeof( vevo_set_func ));
|
|
//memcpy(get_func,d->elements.atom->get_func, sizeof( vevo_get_func ));
|
|
}
|
|
|
|
|
|
//! Construct a new vevo_storage_t object
|
|
/*!
|
|
\param port Port
|
|
\return vevo_storage_t
|
|
*/
|
|
static vevo_storage_t *vevo_new_storage( __vevo_port_t *port)
|
|
//static inline vevo_storage_t *vevo_new_storage(int num_elements)
|
|
{
|
|
vevo_storage_t *d =
|
|
(vevo_storage_t*) vevo_pool_alloc_storage( vevo_storage_t, port->pool );
|
|
// (vevo_storage_t *) vevo_malloc(sizeof(vevo_storage_t));
|
|
veejay_memset( d, 0, sizeof(vevo_storage_t));
|
|
return d;
|
|
}
|
|
|
|
//! Destroy a vevo_storage_t object
|
|
/*!
|
|
\param port port
|
|
\param t vevo_storage_t to destroy
|
|
*/
|
|
static void vevo_free_storage(__vevo_port_t *port,vevo_storage_t * t)
|
|
{
|
|
if (t) {
|
|
if (t->num_elements > 1) {
|
|
int i;
|
|
for (i = 0; i < t->num_elements; i++)
|
|
{
|
|
vevo_free_atom(port,t->elements.array[i]);
|
|
}
|
|
free(t->elements.array);
|
|
}
|
|
if (t->num_elements <= 1)
|
|
{
|
|
vevo_free_atom(port,t->elements.atom);
|
|
}
|
|
vevo_pool_free_storage( port->pool, t );
|
|
}
|
|
t = NULL;
|
|
}
|
|
|
|
//! Cast a key into a hashing value
|
|
/*!
|
|
\param key hash key code
|
|
\return hash value
|
|
*/
|
|
static hash_val_t int_hash(const void *key)
|
|
{
|
|
return (hash_val_t) key;
|
|
}
|
|
|
|
//! Compare two keys
|
|
/*!
|
|
\param key1 key1
|
|
\param key2 key2
|
|
\return error code if keys are unequal
|
|
*/
|
|
static int key_compare(const void *key1, const void *key2)
|
|
{
|
|
return ((const ukey_t) key1 == (const ukey_t) key2 ? 0 : 1);
|
|
}
|
|
|
|
//! Get the number of elements in an Atom
|
|
/*!
|
|
\param p port
|
|
\param key property name
|
|
\return Number of elements
|
|
*/
|
|
int vevo_property_num_elements(vevo_port_t * p, const char *key)
|
|
{
|
|
if(!p) return -1;
|
|
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL)
|
|
return node->st->num_elements;
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
if (stor)
|
|
return stor->num_elements;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//! Get the atom type of a Property
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\return Atom type
|
|
*/
|
|
int vevo_property_atom_type(vevo_port_t * p, const char *key)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL)
|
|
return node->st->atom_type;
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
if (stor)
|
|
return stor->atom_type;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int vevo_storage_size( vevo_storage_t *stor ) {
|
|
int i;
|
|
if( stor->num_elements == 0 )
|
|
return 0;
|
|
if( stor->num_elements == 1 )
|
|
return stor->elements.atom->size;
|
|
int msize = 0;
|
|
for( i = 0; i < stor->num_elements; i ++ ) {
|
|
msize += stor->elements.array[i]->size;
|
|
}
|
|
return msize;
|
|
}
|
|
|
|
int vevo_property_atom_size(vevo_port_t * p, const char *key)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
return vevo_storage_size( node->st );
|
|
}
|
|
else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
if (stor) {
|
|
return vevo_storage_size( stor );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
//! Return size of an Atom at a given index
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\param idx Index
|
|
\return Byte size of value at Index
|
|
*/
|
|
size_t
|
|
vevo_property_element_size(vevo_port_t * p, const char *key, const int idx )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *node;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
if (node->st->num_elements == 1)
|
|
return node->st->elements.atom->size;
|
|
else if (node->st->num_elements > 1)
|
|
return node->st->elements.array[idx]->size;
|
|
return 0;
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node);
|
|
//todo: sum all element sizes for index of -1
|
|
if (stor->num_elements == 1) {
|
|
return stor->elements.atom->size;
|
|
} else if (stor->num_elements > 1) {
|
|
return stor->elements.array[idx]->size;
|
|
}
|
|
else {
|
|
if (stor->num_elements == 0)
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//! Construct a new Port
|
|
/*!
|
|
\param port_type Type of Port to Create. Port types <= 1024 are typed, > 1024 are anonymous ports.
|
|
\return A New Port
|
|
*/
|
|
vevo_port_t *vevo_port_new(int port_type)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) vj_malloc(sizeof(__vevo_port_t));
|
|
|
|
port->index = NULL;
|
|
port->list = NULL;
|
|
port->table = NULL;
|
|
port->pool = vevo_pool_init( sizeof(vevo_property_t),sizeof( vevo_storage_t ), sizeof( atom_t ) , sizeof( port_index_t ) );
|
|
/* If the port type is a Livido port this or that */
|
|
if ( (port_type >= 1 && port_type <= 50) || port_type < 0)
|
|
port->list = NULL;
|
|
else
|
|
port->table = hash_create(HASHCOUNT_T_MAX, key_compare, int_hash);
|
|
|
|
return (vevo_port_t *) port;
|
|
}
|
|
|
|
//! Initialize VeVo. Set up bookkeeping information to track Port construction and destruction
|
|
void vevo_strict_init()
|
|
{
|
|
memset( atom_sizes_,0,sizeof(atom_sizes_) );
|
|
atom_sizes_[1] = sizeof(int32_t);
|
|
atom_sizes_[2] = sizeof(double);
|
|
atom_sizes_[3] = sizeof(int32_t);
|
|
atom_sizes_[4] = sizeof(char*);
|
|
atom_sizes_[8] = sizeof(char*);
|
|
atom_sizes_[5] = sizeof(uint64_t);
|
|
atom_sizes_[65] = sizeof(void*);
|
|
atom_sizes_[66] = sizeof(vevo_port_t*);
|
|
}
|
|
//! Destroy a Port
|
|
/*!
|
|
\param p (local) Port to destroy
|
|
*/
|
|
static void vevo_port_free_(vevo_port_t * p)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
if (port->table) {
|
|
if (!hash_isempty((hash_t *) port->table)) {
|
|
hscan_t scan = (hscan_t) {0};
|
|
hash_scan_begin(&scan, (hash_t *) port->table);
|
|
hnode_t *node = NULL;
|
|
|
|
while ((node = hash_scan_next(&scan)) != NULL) {
|
|
vevo_storage_t *stor = hnode_get(node);
|
|
vevo_free_storage(port,stor);
|
|
hash_delete( (hash_t*) port->table, node );
|
|
hnode_destroy( node );
|
|
}
|
|
hash_free_nodes((hash_t *) port->table);
|
|
}
|
|
hash_destroy((hash_t *) port->table);
|
|
port->table = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
vevo_property_t *l = port->list;
|
|
vevo_property_t *n;
|
|
while (l != NULL) {
|
|
n = l->next;
|
|
if(l->st) {
|
|
vevo_free_storage(port,l->st);
|
|
prop_node_free(port,l);
|
|
}
|
|
l = n;
|
|
}
|
|
port->list = NULL;
|
|
}
|
|
|
|
port_index_t *list = port->index;
|
|
port_index_t *node = list;
|
|
port_index_t *next = NULL;
|
|
while( node != NULL ) {
|
|
next = node->next;
|
|
port_node_free(port, node );
|
|
node = next;
|
|
}
|
|
port->index = NULL;
|
|
vevo_pool_destroy( port->pool );
|
|
|
|
free(port);
|
|
|
|
p = port = NULL;
|
|
}
|
|
|
|
//! Verify if Vevo has allocated a given Port
|
|
/*!
|
|
\param port Port to verify
|
|
\return error code
|
|
*/
|
|
int vevo_port_verify( vevo_port_t *port )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
//! Destroy a Port
|
|
/*!
|
|
\param p Port to destroy
|
|
*/
|
|
void vevo_port_free( vevo_port_t *port )
|
|
{
|
|
if(port != NULL) {
|
|
vevo_port_free_(port );
|
|
port = NULL;
|
|
}
|
|
}
|
|
#ifdef STRICT_CHECKING
|
|
//! Check if a Property is soft referenced
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\return error code
|
|
*/
|
|
static int
|
|
vevo_property_is_soft_referenced(vevo_port_t * p,
|
|
const char *key )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
if (!port->table) {
|
|
vevo_property_t *pnode = NULL;
|
|
if ((pnode = prop_node_get(port, hash_key)) != NULL) {
|
|
return pnode->st->softlink;
|
|
}
|
|
} else {
|
|
hnode_t *old_node = NULL;
|
|
if ((old_node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *oldstor =
|
|
(vevo_storage_t *) hnode_get(old_node);
|
|
return oldstor->softlink;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
//! Store a value as a new Property or overwrite existing value
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\param atom_type Atom type
|
|
\param num_elements Number of elements
|
|
\param src Source address
|
|
\return error code
|
|
*/
|
|
int
|
|
vevo_property_set(vevo_port_t * p,
|
|
const char *key,
|
|
int atom_type, int num_elements, void *src)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
int new = 1;
|
|
void *node = NULL;
|
|
if (!port->table) {
|
|
vevo_property_t *pnode = NULL;
|
|
if ((pnode = prop_node_get(port, hash_key)) != NULL) {
|
|
vevo_free_storage(port,pnode->st);
|
|
//prop_node_free(pnode);
|
|
new = 0;
|
|
node = (void *) pnode;
|
|
}
|
|
} else {
|
|
hnode_t *old_node = NULL;
|
|
if ((old_node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *oldstor =
|
|
(vevo_storage_t *) hnode_get(old_node);
|
|
vevo_free_storage(port,oldstor);
|
|
|
|
hash_delete((hash_t *) port->table, old_node);
|
|
hnode_destroy(old_node);
|
|
new = 0;
|
|
}
|
|
}
|
|
|
|
vevo_storage_t *stor = vevo_new_storage(port);
|
|
storage_put_atom_value(port, src, num_elements, stor, atom_type);
|
|
|
|
if (new) {
|
|
port_node_append(port, key, hash_key);
|
|
|
|
if(!port->table) {
|
|
node = (void *) prop_node_append(port, hash_key, stor);
|
|
}
|
|
}
|
|
|
|
if (!port->table) {
|
|
if (!new) {
|
|
vevo_property_t *current = (vevo_property_t *) node;
|
|
current->st = stor;
|
|
}
|
|
} else {
|
|
hnode_t *node2 = hnode_create(stor);
|
|
hash_insert((hash_t *) port->table, node2, (const void *) hash_key);
|
|
}
|
|
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO, "Port %p <- set property %s", port, key );
|
|
#endif
|
|
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
int
|
|
vevo_property_set_f(vevo_port_t * p,
|
|
const char *key,
|
|
int atom_type, int num_elements, void (*set_func)(), int (*get_func)() )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
int new = 1;
|
|
void *node = NULL;
|
|
if (!port->table) {
|
|
vevo_property_t *pnode = NULL;
|
|
if ((pnode = prop_node_get(port, hash_key)) != NULL) {
|
|
vevo_free_storage(port,pnode->st);
|
|
//prop_node_free(pnode);
|
|
new = 0;
|
|
node = (void *) pnode;
|
|
}
|
|
} else {
|
|
hnode_t *old_node = NULL;
|
|
if ((old_node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *oldstor =
|
|
(vevo_storage_t *) hnode_get(old_node);
|
|
vevo_free_storage(port,oldstor);
|
|
|
|
hash_delete((hash_t *) port->table, old_node);
|
|
hnode_destroy(old_node);
|
|
new = 0;
|
|
}
|
|
}
|
|
vevo_storage_t *stor = vevo_new_storage(port);
|
|
|
|
storage_put_atom_func(port, set_func,get_func, stor, atom_type);
|
|
|
|
if (new) {
|
|
port_node_append(port, key, hash_key);
|
|
if (!port->table)
|
|
node = (void *) prop_node_append(port, hash_key, stor);
|
|
}
|
|
|
|
if (!port->table) {
|
|
if (!new) {
|
|
vevo_property_t *current = (vevo_property_t *) node;
|
|
current->st = stor;
|
|
}
|
|
} else {
|
|
hnode_t *node2 = hnode_create(stor);
|
|
|
|
hash_insert((hash_t *) port->table, node2,
|
|
(const void *) hash_key);
|
|
}
|
|
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO, "Port %p <- set property %s", port, key );
|
|
#endif
|
|
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
//! Get a value from a Property
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\param idx Index
|
|
\param dst Destination address
|
|
\return error code
|
|
*/
|
|
int
|
|
vevo_property_get(vevo_port_t * p, const char *key, int idx, void *dst)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> get property %s[%d]",port,key,idx );
|
|
#endif
|
|
return atom_get_value(node->st, idx, dst);
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> get property %s[%d]", port,key,idx );
|
|
#endif
|
|
|
|
return atom_get_value((vevo_storage_t *) hnode_get(node),
|
|
idx, dst);
|
|
}
|
|
}
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> no such property %s[%d]", port,key,idx );
|
|
#endif
|
|
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
//! Get a value from a Property
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\param idx Index
|
|
\param dst Destination address
|
|
\return error code
|
|
*/
|
|
int
|
|
vv_property_get(vevo_port_t * p, uint64_t hash_key, int idx, void *dst)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
vevo_property_t *node = NULL;
|
|
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
return atom_get_value(node->st, idx, dst);
|
|
}
|
|
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
|
|
//! Store a value as a new Property or overwrite existing value
|
|
/*!
|
|
\param p Port
|
|
\param key Property name
|
|
\param atom_type Atom type
|
|
\param num_elements Number of elements
|
|
\param src Source address
|
|
\return error code
|
|
*/
|
|
int
|
|
vv_property_set(vevo_port_t * p,
|
|
uint64_t hash_key,
|
|
int atom_type, int num_elements, void *src)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
int new = 1;
|
|
void *node = NULL;
|
|
vevo_property_t *pnode = NULL;
|
|
if ((pnode = prop_node_get(port, hash_key)) != NULL) {
|
|
vevo_free_storage(port,pnode->st);
|
|
new = 0;
|
|
node = (void *) pnode;
|
|
}
|
|
|
|
vevo_storage_t *stor = vevo_new_storage(port);
|
|
storage_put_atom_value(port, src, num_elements, stor, atom_type);
|
|
|
|
if (new) {
|
|
prop_node_append(port, hash_key, stor);
|
|
} else {
|
|
vevo_property_t *current = (vevo_property_t *) node;
|
|
current->st = stor;
|
|
}
|
|
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
int vevo_property_call(vevo_port_t * p, const char *key, void *ctx, int32_t type, int32_t value )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> call property %s",port,key );
|
|
#endif
|
|
vevo_storage_t *s = node->st;
|
|
vevo_set_func vvfunc = (vevo_set_func) s->elements.atom->set_func;
|
|
vvfunc( ctx,type, value );
|
|
return 1;
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> call property %s", port,key );
|
|
#endif
|
|
vevo_storage_t *s = (vevo_storage_t*) hnode_get(node);
|
|
vevo_set_func vvfunc = (vevo_set_func) s->elements.atom->set_func;
|
|
vvfunc( ctx,type, value );
|
|
return 1;
|
|
}
|
|
}
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> no such property %s", port,key );
|
|
#endif
|
|
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
int
|
|
vevo_property_call_get(vevo_port_t * p, const char *key, void *ctx )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
ukey_t hash_key = hash_key_code(key);
|
|
|
|
if (!port->table) {
|
|
vevo_property_t *node = NULL;
|
|
if ((node = prop_node_get(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> call property %s",port,key );
|
|
#endif
|
|
vevo_storage_t *s = node->st;
|
|
vevo_get_func vvfunc = (vevo_get_func) s->elements.atom->get_func;
|
|
return vvfunc( ctx );
|
|
}
|
|
} else {
|
|
hnode_t *node = NULL;
|
|
if ((node = property_exists(port, hash_key)) != NULL) {
|
|
// if (dst == NULL)
|
|
// return VEVO_NO_ERROR;
|
|
// else
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> call property %s", port,key );
|
|
#endif
|
|
vevo_storage_t *s = (vevo_storage_t*) hnode_get(node);
|
|
vevo_get_func vvfunc = (vevo_get_func) s->elements.atom->get_func;
|
|
return vvfunc( ctx );
|
|
}
|
|
}
|
|
#ifdef VVERBOSE
|
|
veejay_msg(VEEJAY_MSG_INFO ,"Port %p -> no such property %s", port,key );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//! List all properties in a Port
|
|
/*!
|
|
\param p Port
|
|
\return Null terminated list of property names
|
|
*/
|
|
char **vevo_list_properties(vevo_port_t * p)
|
|
{
|
|
if(!p) return NULL;
|
|
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
|
|
if(!port->index)
|
|
return NULL;
|
|
|
|
char **list = NULL;
|
|
int n = 0;
|
|
int i = 0;
|
|
|
|
port_index_t *l = port->index;
|
|
while (l != NULL) {
|
|
n++;
|
|
l = l->next;
|
|
}
|
|
|
|
if( n <= 0 )
|
|
return NULL;
|
|
|
|
list = (char **) vj_malloc(sizeof(char *) * (n+1) );
|
|
if (!list)
|
|
return NULL;
|
|
|
|
l = (port_index_t *) port->index;
|
|
|
|
while (l != NULL) {
|
|
list[i] = (char *) vj_strdup(l->key);
|
|
i++;
|
|
l = l->next;
|
|
//i++;
|
|
}
|
|
|
|
list[n] = NULL;
|
|
return list;
|
|
}
|
|
|
|
int vevo_num_properties(vevo_port_t * p)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
if(!port->index)
|
|
return 0;
|
|
|
|
int n = 0;
|
|
port_index_t *l = port->index;
|
|
while (l != NULL) {
|
|
l = l->next;
|
|
n++;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
//! List all Properties in a Port that match Atom type
|
|
/*!
|
|
\param p Port
|
|
\param atype Atom type
|
|
\return List of vevo_storage_t
|
|
*/
|
|
static vevo_storage_t **vevo_list_nodes_(vevo_port_t * p, int atype)
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
if(!p) return NULL;
|
|
|
|
unsigned int N = 8; // null terminated list of keys 2 -> 4 -> 8 -> 16 etc
|
|
int idx = 0;
|
|
|
|
vevo_storage_t **list = (vevo_storage_t**) malloc(sizeof(vevo_storage_t*) * N ); // realloc does not guarantee same alignment
|
|
|
|
if( port->table)
|
|
{
|
|
hnode_t *node = NULL;
|
|
hscan_t scan = (hscan_t) { 0 };
|
|
vevo_storage_t *s = NULL;
|
|
hash_scan_begin( &scan,(hash_t*) port->table );
|
|
while((node=hash_scan_next(&scan)) != NULL)
|
|
{
|
|
s = hnode_get(node);
|
|
if (s != NULL && (s->atom_type == atype || atype == 0))
|
|
{
|
|
int type = 0;
|
|
int ec = atom_get_value(s, 0, &type);
|
|
if( ec == VEVO_NO_ERROR && !s->softlink ) {
|
|
list[idx] = s;
|
|
idx ++;
|
|
if( idx >= N ) {
|
|
N *= 2;
|
|
list = (vevo_storage_t**) realloc( list, sizeof(vevo_storage_t*) * N );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
list[idx] = NULL;
|
|
}
|
|
else
|
|
{
|
|
vevo_property_t *l = port->list;
|
|
vevo_property_t *n = NULL;
|
|
vevo_storage_t *s = NULL;
|
|
while( l != NULL )
|
|
{
|
|
n = l->next;
|
|
s = l->st;
|
|
|
|
if(s != NULL && (s->atom_type == atype || atype == 0) )
|
|
{
|
|
int type = 0;
|
|
int ec = atom_get_value(l->st, 0, &type);
|
|
if( ec == VEVO_NO_ERROR && !s->softlink ) {
|
|
list[idx] = s;
|
|
idx ++;
|
|
if( idx >= N ) {
|
|
N *= 2;
|
|
list = (vevo_storage_t**) realloc( list, sizeof(vevo_storage_t*) * N );
|
|
}
|
|
}
|
|
}
|
|
l = n;
|
|
}
|
|
list[idx] = NULL;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
//! Report statistics and free bookkeeping information
|
|
void vevo_report_stats()
|
|
{
|
|
}
|
|
|
|
static int vevo_port_get_port( void *port, vevo_storage_t *item, void *res )
|
|
{
|
|
if (item->flags & VEVO_PROPERTY_SOFTREF)
|
|
return -1;
|
|
if(item->num_elements == 1 )
|
|
atom_get_value( item, 0, res );
|
|
return item->num_elements;
|
|
}
|
|
|
|
//! Add a Port to the reference port or create a new reference port
|
|
/*!
|
|
\param in Input port
|
|
\param ref Reference Port
|
|
\return New port or Input port
|
|
*/
|
|
void *vevo_port_register( vevo_port_t *in, vevo_port_t *ref )
|
|
{
|
|
void *port = in;
|
|
const void *store = ref;
|
|
if(!port)
|
|
port = vevo_port_new( VEVO_PORT_POOL );
|
|
char pkey[32];
|
|
if(store)
|
|
{
|
|
sprintf(pkey,"%p", ref);
|
|
if( vevo_property_exists( port, pkey ) == 0 )
|
|
vevo_property_set( port, pkey,VEVO_ATOM_TYPE_PORTPTR, 1 , &ref );
|
|
}
|
|
return port;
|
|
}
|
|
|
|
//! Merge 2 Ports, A + B = AB. Only for properties that have atom VOIDPTR
|
|
/**! all in port_a is added to port_b
|
|
\param port Port A
|
|
\param port Port B
|
|
\return Error code
|
|
*/
|
|
int vevo_union_ports( void *port_a, void *port_b, int filter_type )
|
|
{
|
|
__vevo_port_t *A = (__vevo_port_t *) port_a;
|
|
__vevo_port_t *B = (__vevo_port_t *) port_b;
|
|
|
|
if(!A || !B )
|
|
return 1;
|
|
|
|
char **Ea = vevo_list_properties( port_a );
|
|
int i;
|
|
for( i = 0; Ea[i] != NULL; i ++ )
|
|
{
|
|
if(!vevo_property_exists( port_b, Ea[i] )&& vevo_property_atom_type( port_a, Ea[i] ) ==
|
|
filter_type )
|
|
{
|
|
void *v = NULL;
|
|
if(vevo_property_get( port_a, Ea[i], 0, &v ) == VEVO_NO_ERROR ) {
|
|
vevo_property_set( port_b, Ea[i],VEVO_ATOM_TYPE_VOIDPTR,1, &v );
|
|
}
|
|
}
|
|
free( Ea[i] );
|
|
}
|
|
free( Ea );
|
|
|
|
return 0;
|
|
}
|
|
|
|
//! Adds all elements in port_b of type VOIDPTR to port_a. Key value tupple is reversed.
|
|
/*!
|
|
* \param port Port A
|
|
\param port Port B
|
|
\return Error code
|
|
*/
|
|
|
|
int vevo_special_union_ports( void *port_a, void *port_b )
|
|
{
|
|
__vevo_port_t *A = (__vevo_port_t *) port_a;
|
|
__vevo_port_t *B = (__vevo_port_t *) port_b;
|
|
|
|
if(!A || !B )
|
|
return 0;
|
|
|
|
// port_a contains only slots
|
|
|
|
char **Ea = vevo_list_properties( port_a );
|
|
int i;
|
|
if(!Ea)
|
|
return 0;
|
|
|
|
char key[64];
|
|
for( i = 0; Ea[i] != NULL; i ++ )
|
|
{
|
|
void *value = NULL;
|
|
int atom_type = vevo_property_atom_type( port_a, Ea[i] );
|
|
if( atom_type == VEVO_ATOM_TYPE_VOIDPTR )
|
|
{
|
|
if( vevo_property_get( port_a, Ea[i], 0, &value ) == VEVO_NO_ERROR )
|
|
{
|
|
snprintf(key,sizeof(key), "%p", value );
|
|
if(!vevo_property_exists( port_b, key ))
|
|
vevo_property_set( port_b, key, VEVO_ATOM_TYPE_VOIDPTR,1,&value );
|
|
}
|
|
}
|
|
free( Ea[i] );
|
|
}
|
|
free( Ea );
|
|
return 0;
|
|
}
|
|
//! Recursivly destroy a Port and all sub ports
|
|
/**!
|
|
\param port Port to destroy
|
|
*/
|
|
|
|
|
|
int vevo_port_get_total_size( vevo_port_t *port )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void vevo_port_recursive_free( vevo_port_t *port )
|
|
{
|
|
if(port == NULL)
|
|
return;
|
|
|
|
__vevo_port_t *vp = (__vevo_port_t *) port;
|
|
if( vp->index == NULL ) {
|
|
port = NULL;
|
|
return;
|
|
}
|
|
|
|
vevo_storage_t **item = vevo_list_nodes_( port, VEVO_ATOM_TYPE_PORTPTR );
|
|
if(!item)
|
|
{
|
|
vevo_port_free_( port );
|
|
port = NULL;
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
|
|
for( i = 0; item[i] != NULL ; i ++ )
|
|
{
|
|
void *q = NULL;
|
|
int n = vevo_port_get_port( port, item[i], &q );
|
|
|
|
if( n == 1 && q != NULL )
|
|
{
|
|
vevo_port_recursive_free( q );
|
|
}
|
|
else
|
|
{
|
|
if( n > 1 )
|
|
{
|
|
int k = 0;
|
|
for( k = 0; k < item[i]->num_elements; k ++ )
|
|
{
|
|
void *qq = NULL;
|
|
int err = atom_get_value( item[i], k, &qq );
|
|
if( err != VEVO_NO_ERROR )
|
|
continue;
|
|
vevo_port_recursive_free( qq );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(item);
|
|
vevo_port_free_( port );
|
|
port = NULL;
|
|
}
|
|
|
|
static char *vevo_property_get_str( vevo_port_t *port, const char *key )
|
|
{
|
|
size_t len = vevo_property_element_size( port, key,0 );
|
|
char *ret = NULL;
|
|
if(len<=0) return NULL;
|
|
ret = (char*) vj_malloc(sizeof(char) * len );
|
|
vevo_property_get( port, key, 0, &ret );
|
|
return ret;
|
|
}
|
|
|
|
static char *vevo_format_inline_property( vevo_port_t *port, int n_elem, int type )
|
|
{
|
|
char *res = NULL;
|
|
char token[5] = { 0 };
|
|
switch(type)
|
|
{
|
|
case VEVO_ATOM_TYPE_INT:
|
|
token[0] = 'd';
|
|
break;
|
|
case VEVO_ATOM_TYPE_BOOL:
|
|
token[0] = 'b';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UINT64:
|
|
token[0] = 'D';
|
|
break;
|
|
case VEVO_ATOM_TYPE_STRING:
|
|
token[0] = 's';
|
|
break;
|
|
case VEVO_ATOM_TYPE_DOUBLE:
|
|
token[0] = 'g';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UTF8STRING:
|
|
token[0] = 'S';
|
|
break;
|
|
|
|
}
|
|
|
|
if( token[0])
|
|
{
|
|
int len = n_elem * strlen(token) + 1;
|
|
res = (char*) calloc(1, sizeof(char) * len );
|
|
/*for( i =0; i < n_elem; i ++ ) {
|
|
while( *res ) *res ++;
|
|
while( *res++ = *token++ );
|
|
res--;
|
|
} FIXME: test me
|
|
*/
|
|
strncat( res,token,strlen(token) );
|
|
}
|
|
return res;
|
|
}
|
|
|
|
char *vevo_format_property( vevo_port_t *port, const char *key )
|
|
{
|
|
char *res = NULL;
|
|
char token[5];
|
|
int atom_type = vevo_property_atom_type( port, key );
|
|
|
|
int n_elem = vevo_property_num_elements( port, key );
|
|
|
|
if( n_elem <= 0 )
|
|
n_elem = 1;
|
|
|
|
switch( atom_type )
|
|
{
|
|
case VEVO_ATOM_TYPE_INT:
|
|
case VEVO_ATOM_TYPE_BOOL:
|
|
token[0] = 'd';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UINT64:
|
|
token[0] = 'D';
|
|
break;
|
|
case VEVO_ATOM_TYPE_DOUBLE:
|
|
token[0] = 'g';
|
|
break;
|
|
case VEVO_ATOM_TYPE_STRING:
|
|
token[0] = 's';
|
|
break;
|
|
case VEVO_ATOM_TYPE_VOIDPTR:
|
|
token[0] = 'x';
|
|
break;
|
|
case VEVO_ATOM_TYPE_PORTPTR:
|
|
token[0] = 'p';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UTF8STRING:
|
|
token[0] = 'S';
|
|
break;
|
|
default:
|
|
token[0] = 'g';
|
|
break;
|
|
}
|
|
|
|
token[1] = '\0';
|
|
|
|
int len = n_elem * strlen(token);
|
|
res = (char*) vj_malloc( sizeof(char) * len + 1 );
|
|
int i;
|
|
for( i =0; i < n_elem; i ++ )
|
|
res[i] = token[0];
|
|
res[len] = '\0';
|
|
|
|
return res;
|
|
|
|
}
|
|
char *vevo_format_kind( vevo_port_t *port, const char *key )
|
|
{
|
|
char token[5];
|
|
int atom_type = vevo_property_atom_type( port, key );
|
|
|
|
token[1] = '\0';
|
|
|
|
switch( atom_type )
|
|
{
|
|
case VEVO_ATOM_TYPE_INT:
|
|
case VEVO_ATOM_TYPE_BOOL:
|
|
token[0] = 'd';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UINT64:
|
|
token[0] = 'D';
|
|
break;
|
|
case VEVO_ATOM_TYPE_DOUBLE:
|
|
token[0] = 'g';
|
|
break;
|
|
case VEVO_ATOM_TYPE_STRING:
|
|
token[0] = 's';
|
|
break;
|
|
case VEVO_ATOM_TYPE_VOIDPTR:
|
|
token[0] = 'x';
|
|
break;
|
|
case VEVO_ATOM_TYPE_PORTPTR:
|
|
token[0] = 'p';
|
|
break;
|
|
case VEVO_ATOM_TYPE_UTF8STRING:
|
|
token[0] = 'S';
|
|
break;
|
|
default:
|
|
token[0] = 'g';
|
|
break;
|
|
}
|
|
|
|
return vj_strdup( token );
|
|
}
|
|
|
|
|
|
static const char *vevo_split_token_( const char *s, const char delim, char *buf, int buf_len )
|
|
{
|
|
const char *c = s;
|
|
int n = 0;
|
|
|
|
while( c[n] != '\0' )
|
|
{
|
|
if( c[n] == delim )
|
|
{
|
|
strncpy( buf,s,n );
|
|
return s + n + 1;
|
|
}
|
|
|
|
n++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static char *vevo_scan_token_( const char *s )
|
|
{
|
|
const char *c = s;
|
|
unsigned int n = 0;
|
|
while( c[n] != '\0' )
|
|
{
|
|
if(c[n] == ':') {
|
|
return vj_strndup( s, n + 1 );
|
|
}
|
|
n ++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const char *vevo_split_token_q( const char *s, const char delim, char *buf, int buf_len )
|
|
{
|
|
const char *c = s;
|
|
unsigned int n = 0;
|
|
|
|
if( c[n] != '"' )
|
|
return NULL;
|
|
|
|
while( c[n] != '\0' )
|
|
{
|
|
if(c[n] == delim) {
|
|
strncpy( buf, s + 1, n - 1 );
|
|
return c;
|
|
}
|
|
n ++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//! Write all keys and values in character string to a port'
|
|
/*!
|
|
\param port Port
|
|
\param s Character string
|
|
\return Error Code
|
|
*/
|
|
int vevo_sscanf_port( vevo_port_t *port, const char *s )
|
|
{
|
|
|
|
const char *ptr = s;
|
|
int len = strlen(s);
|
|
int i = 0;
|
|
while( len > 0 )
|
|
{
|
|
char *token = vevo_scan_token_(ptr);
|
|
int token_len;
|
|
if( token )
|
|
{
|
|
token_len = strlen(token);
|
|
if(vevo_sscanf_property( port, token ))
|
|
i++;
|
|
free(token);
|
|
}
|
|
else
|
|
{
|
|
token_len = len;
|
|
if(vevo_sscanf_property( port, ptr ))
|
|
i++;
|
|
}
|
|
len -= token_len;
|
|
ptr += token_len;
|
|
}
|
|
return i;
|
|
}
|
|
//! Read a key and value from a character string into a Port'
|
|
/*!
|
|
\param port Port
|
|
\param s character string
|
|
\return error code
|
|
*/
|
|
#define MAX_ELEMENTS 64
|
|
int vevo_sscanf_property( vevo_port_t *port, const char *s)
|
|
{
|
|
int done = 0;
|
|
char key[PROPERTY_KEY_SIZE];
|
|
memset( key,0,sizeof(key));
|
|
|
|
const char *value = vevo_split_token_(s, '=', key, PROPERTY_KEY_SIZE );
|
|
if(value==NULL)
|
|
return 0;
|
|
|
|
char *format = vevo_format_property( port, key );
|
|
int atom = vevo_property_atom_type( port, key );
|
|
|
|
if( format == NULL )
|
|
return done;
|
|
|
|
if( atom == VEVO_ATOM_TYPE_FUNCPTR ) {
|
|
void *drv = NULL;
|
|
int err = vevo_property_get( port, "driver", 0, &drv );
|
|
if( drv == NULL || err != VEVO_NO_ERROR ) {
|
|
veejay_msg(0, "No context for property '%s'", s );
|
|
free(format);
|
|
return 0;
|
|
}
|
|
|
|
int32_t v;
|
|
if( sscanf( value, "%d", &v ) ) {
|
|
vevo_property_call( port, key, drv, v,v );
|
|
free(format);
|
|
return 1;
|
|
}
|
|
free(format);
|
|
return 0;
|
|
}
|
|
|
|
if(atom==-1)
|
|
atom = VEVO_ATOM_TYPE_DOUBLE;
|
|
//@ if a property does not exist, DOUBLE is assumed
|
|
//@ DOUBLE is valid for all sample's of type capture.
|
|
|
|
uint64_t i64_val[MAX_ELEMENTS];
|
|
int32_t i32_val[MAX_ELEMENTS];
|
|
double dbl_val[MAX_ELEMENTS];
|
|
char *str_val[MAX_ELEMENTS];
|
|
|
|
int cur_elem = 0;
|
|
int n = 0;
|
|
|
|
const char *p = value;
|
|
char *fmt = format;
|
|
|
|
char arg[1024];
|
|
|
|
while( fmt[cur_elem] != '\0' )
|
|
{
|
|
veejay_memset(arg,0,sizeof(arg));
|
|
|
|
if( fmt[cur_elem] == 's' )
|
|
p = vevo_split_token_q( p, ':', arg, sizeof(arg) );
|
|
else
|
|
p = vevo_split_token_( p, ':', arg, sizeof(arg) );
|
|
|
|
if( p == NULL )
|
|
return 0;
|
|
|
|
if( arg[0] != ':' )
|
|
{
|
|
switch(fmt[cur_elem])
|
|
{
|
|
case 'd':
|
|
n = sscanf( arg, "%d", &(i32_val[cur_elem]));
|
|
break;
|
|
case 'D':
|
|
n = sscanf( arg, "%" SCNd64, &(i64_val[cur_elem]));
|
|
break;
|
|
case 'g':
|
|
n = sscanf( arg, "%lf", &(dbl_val[cur_elem]));
|
|
break;
|
|
case 's':
|
|
str_val[cur_elem] = vj_strdup( arg );
|
|
n = 1;
|
|
break;
|
|
default:
|
|
n = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
n = 0;
|
|
}
|
|
|
|
cur_elem ++;
|
|
|
|
}
|
|
|
|
void *ptr = NULL;
|
|
if( n > 0 )
|
|
switch( format[0] )
|
|
{
|
|
case 'd':
|
|
ptr = &(i32_val[0]);
|
|
break;
|
|
case 'D':
|
|
ptr = &(i64_val[0]);
|
|
break;
|
|
case 'g':
|
|
ptr = &(dbl_val[0]);
|
|
break;
|
|
case 's':
|
|
ptr = &(str_val[0]);
|
|
break;
|
|
}
|
|
|
|
int error = 0;
|
|
|
|
if( n == 0 )
|
|
error = vevo_property_set( port, key, atom, 0, NULL );
|
|
else
|
|
error = vevo_property_set( port, key, atom, cur_elem, ptr );
|
|
|
|
if( error == VEVO_NO_ERROR )
|
|
done = 1;
|
|
|
|
free(format);
|
|
|
|
return done;
|
|
}
|
|
|
|
//! Write all properties in a port to a new character string in the form 'key=[value:value:value]:'
|
|
/*!
|
|
\param port Port
|
|
\return A new character string
|
|
*/
|
|
char **vevo_sprintf_port( vevo_port_t *port )
|
|
{
|
|
int i;
|
|
int k = 0;
|
|
int num = vevo_num_properties(port);
|
|
if( num == 0 )
|
|
return NULL;
|
|
|
|
char **keys = vevo_list_properties(port );
|
|
|
|
char **res = (char**) calloc(1, sizeof(char*) * (num+1) );
|
|
|
|
for( i = 0; keys[i] != NULL; i ++ )
|
|
{
|
|
char *buf = vevo_sprintf_property(port, keys[i]);
|
|
if(buf)
|
|
{
|
|
res[k++] = buf;
|
|
}
|
|
free(keys[i]);
|
|
|
|
}
|
|
res[num] = NULL;
|
|
|
|
free(keys);
|
|
|
|
return res;
|
|
}
|
|
//! Write property value to a new character string in the form 'key=[value:value:value]:'
|
|
/*!
|
|
\param port Port
|
|
\param key Property to write
|
|
\return A new character string
|
|
*/
|
|
|
|
char *vevo_sprintf_property_value( vevo_port_t *port, const char *key)
|
|
{
|
|
char tmp[512];
|
|
char val[64];
|
|
int n = vevo_property_num_elements( port, key );
|
|
if( n <= 0 ) {
|
|
return vj_strdup("<empty>");
|
|
}
|
|
|
|
int i;
|
|
int atom = vevo_property_atom_type( port , key );
|
|
|
|
veejay_memset(tmp,0,sizeof(tmp));
|
|
veejay_memset(val,0,sizeof(val));
|
|
|
|
if(atom == VEVO_ATOM_TYPE_INT || atom == VEVO_ATOM_TYPE_BOOL)
|
|
{
|
|
int *a = (int*) vj_calloc(sizeof(int) * n );
|
|
for( i = 0; i < n ; i ++ ) {
|
|
if( vevo_property_get( port, key, i, &(a[i]) ) != VEVO_NO_ERROR)
|
|
{
|
|
free(a);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
snprintf(val,sizeof(val), "'%d'", a[i]);
|
|
strcat( tmp, val );
|
|
strcat( tmp, " ");
|
|
}
|
|
}
|
|
free(a);
|
|
} else if (atom == VEVO_ATOM_TYPE_DOUBLE )
|
|
{
|
|
double *a = (double*) vj_calloc(sizeof(double) * n );
|
|
for( i = 0; i < n; i ++ ) {
|
|
if( vevo_property_get( port, key, i , &(a[i])) != VEVO_NO_ERROR)
|
|
{
|
|
free(a);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
snprintf(val,sizeof(val), "'%g'", a[i]);
|
|
strcat( tmp, val );
|
|
strcat( tmp, " " );
|
|
}
|
|
}
|
|
free(a);
|
|
} else if ( atom == VEVO_ATOM_TYPE_UINT64 ) {
|
|
uint64_t *a = (uint64_t*) vj_calloc(sizeof(uint64_t)*n);
|
|
for( i = 0; i < n; i ++ ) {
|
|
if( vevo_property_get(port,key,i, &(a[i])) != VEVO_NO_ERROR ) {
|
|
free(a);
|
|
return NULL;
|
|
}
|
|
else {
|
|
snprintf(val,sizeof(val), "'%" PRId64 "'", a[i]);
|
|
strcat(tmp,val);
|
|
strcat(tmp," ");
|
|
}
|
|
}
|
|
free(a);
|
|
}
|
|
else if ( atom == VEVO_ATOM_TYPE_STRING || atom == VEVO_ATOM_TYPE_UTF8STRING ) {
|
|
size_t len = vevo_property_element_size( port, key ,0);
|
|
if( len > 0 ) {
|
|
char *strv = vevo_property_get_string(port,key);
|
|
strcat(tmp, strv );
|
|
strcat(tmp, " ");
|
|
free(strv);
|
|
}
|
|
} else
|
|
{
|
|
return NULL;
|
|
}
|
|
return vj_strdup( tmp );
|
|
}
|
|
|
|
|
|
#define PROP_MAX_LEN 1024
|
|
#define PROP_ARG_LEN 256
|
|
char *vevo_sprintf_property( vevo_port_t *port, const char *key )
|
|
{
|
|
char *format = vevo_format_property( port, key );
|
|
if( format == NULL )
|
|
return NULL;
|
|
char *res = (char*) calloc( 1, sizeof(char) * PROP_MAX_LEN );
|
|
int n_elems = 0;
|
|
|
|
int32_t i32_val = 0;
|
|
uint64_t i64_val = 0;
|
|
double dbl_val = 0.0;
|
|
char *str_val = NULL;
|
|
int error = 0;
|
|
int nerr = 0;
|
|
int size = PROP_MAX_LEN;
|
|
|
|
void *vport = NULL;
|
|
char tmp[1024];
|
|
|
|
snprintf(res, PROP_MAX_LEN, "%s=", key );
|
|
|
|
while( format[n_elems] && nerr == 0)
|
|
{
|
|
veejay_memset(tmp,0,sizeof(tmp));
|
|
switch(format[n_elems])
|
|
{
|
|
case 'd':
|
|
error = vevo_property_get(port,key,n_elems,&i32_val);
|
|
if( error == VEVO_NO_ERROR ) {
|
|
sprintf(tmp, "%d:", i32_val );
|
|
} else if (error == VEVO_ERROR_PROPERTY_EMPTY ) {
|
|
tmp[0] = ':';
|
|
} else
|
|
nerr ++;
|
|
break;
|
|
case 'D':
|
|
error = vevo_property_get(port,key,n_elems,&i64_val);
|
|
if( error == VEVO_NO_ERROR ) {
|
|
sprintf(tmp, "%" PRId64 ":", i64_val );
|
|
} else if( error == VEVO_ERROR_PROPERTY_EMPTY ) {
|
|
tmp[0] = ':';
|
|
} else
|
|
nerr ++;
|
|
break;
|
|
case 'g':
|
|
error = vevo_property_get(port,key,n_elems,&dbl_val);
|
|
if( error == VEVO_NO_ERROR ) {
|
|
sprintf(tmp, "%g:", dbl_val );
|
|
} else if ( error == VEVO_ERROR_PROPERTY_EMPTY ) {
|
|
tmp[0] = ':';
|
|
} else
|
|
nerr ++;
|
|
break;
|
|
case 's':
|
|
case 'S':
|
|
str_val = vevo_property_get_str( port, key );
|
|
if(str_val)
|
|
{
|
|
tmp[0] = '\"';
|
|
strncat(tmp+1,str_val,250);
|
|
int n = strlen(tmp);
|
|
tmp[n] = '\"';
|
|
tmp[n+1] = ':';
|
|
}
|
|
else
|
|
{
|
|
tmp[0] = '\"';
|
|
tmp[1] = '\"';
|
|
tmp[2] = ':';
|
|
}
|
|
str_val = NULL;
|
|
break;
|
|
case 'x':
|
|
break;
|
|
case 'p':
|
|
{
|
|
int num = 0;
|
|
if(n_elems == 0 )
|
|
{
|
|
error = vevo_property_get(port,key,0,&vport );
|
|
if(error == VEVO_NO_ERROR )
|
|
num = vevo_num_properties(vport);
|
|
}
|
|
|
|
if( num > 0 )
|
|
{
|
|
char **pstr = vevo_sprintf_port( vport );
|
|
if(pstr)
|
|
{
|
|
int k;
|
|
|
|
sprintf(tmp, "[%s",key);
|
|
|
|
for( k = 0; pstr[k] != NULL; k ++ )
|
|
{
|
|
strncat(tmp, pstr[k], strlen(pstr[k]));
|
|
free(pstr[k]);
|
|
}
|
|
free(pstr);
|
|
|
|
int n = strlen(tmp);
|
|
tmp[n] =']';
|
|
tmp[n+1] = ':';
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
n_elems++;
|
|
|
|
if( nerr )
|
|
break;
|
|
|
|
size -= strlen(tmp);
|
|
if(size > 0)
|
|
strcat(res, tmp );
|
|
else
|
|
nerr++;
|
|
}
|
|
|
|
if( nerr )
|
|
{
|
|
if( res ) free(res);
|
|
res = NULL;
|
|
}
|
|
|
|
free(format);
|
|
|
|
return res;
|
|
}
|
|
int vevo_property_from_string( vevo_port_t *port, const char *s, const char *key, int n_elem, int type)
|
|
{
|
|
int done = 0;
|
|
char *format = vevo_format_inline_property( port, n_elem, type );
|
|
|
|
if( format == NULL )
|
|
return done;
|
|
|
|
uint64_t i64_val[MAX_ELEMENTS];
|
|
int32_t i32_val[MAX_ELEMENTS];
|
|
double dbl_val[MAX_ELEMENTS];
|
|
char *str_val[MAX_ELEMENTS];
|
|
|
|
int cur_elem = 0;
|
|
int n = 0;
|
|
const char *p = s;
|
|
char *fmt = format;
|
|
|
|
char arg[256];
|
|
|
|
while( fmt[cur_elem] != '\0' )
|
|
{
|
|
veejay_memset(arg,0,sizeof(arg));
|
|
|
|
if( fmt[cur_elem] == 's' )
|
|
p = vevo_split_token_q( p, ':', arg, sizeof(arg) );
|
|
else
|
|
p = vevo_split_token_( p, ':', arg,sizeof(arg) );
|
|
|
|
if( p == NULL )
|
|
{
|
|
veejay_msg(0,"Invalid value. Use 'value:' ");
|
|
free(format);
|
|
return 0;
|
|
}
|
|
|
|
if( arg[0] != ':' )
|
|
{
|
|
switch(fmt[cur_elem])
|
|
{
|
|
case 'd':
|
|
case 'b':
|
|
n = sscanf( arg, "%d", &(i32_val[cur_elem]));
|
|
break;
|
|
case 'D':
|
|
n = sscanf( arg, "%" PRId64, &(i64_val[cur_elem]));
|
|
break;
|
|
case 'g':
|
|
n = sscanf( arg, "%lf", &(dbl_val[cur_elem]));
|
|
break;
|
|
case 's':
|
|
str_val[cur_elem] = vj_strdup( arg );
|
|
n = 1;
|
|
break;
|
|
default:
|
|
n = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
n = 0;
|
|
}
|
|
|
|
cur_elem ++;
|
|
}
|
|
|
|
void *ptr = NULL;
|
|
int ret;
|
|
if( n > 0 )
|
|
{
|
|
switch( format[0] )
|
|
{
|
|
case 'd':
|
|
case 'b':
|
|
ptr = &(i32_val[0]);
|
|
break;
|
|
case 'D':
|
|
ptr = &(i64_val[0]);
|
|
break;
|
|
case 'g':
|
|
ptr = &(dbl_val[0]);
|
|
break;
|
|
case 's':
|
|
ptr = &(str_val[0]);
|
|
break;
|
|
default:
|
|
n = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( n == 0 )
|
|
ret = vevo_property_set( port, key, type, 0, NULL );
|
|
else
|
|
ret = vevo_property_set( port, key, type, cur_elem, ptr );
|
|
|
|
if( ret == VEVO_NO_ERROR )
|
|
done = 1;
|
|
|
|
free(format);
|
|
return done;
|
|
}
|
|
|
|
char *vevo_property_get_string( void *port, const char *key )
|
|
{
|
|
size_t len = vevo_property_element_size( port, key,0 );
|
|
char *ret = NULL;
|
|
|
|
if(len<=0)
|
|
return NULL;
|
|
|
|
if( vevo_property_get( port, key,0,NULL ) != VEVO_NO_ERROR )
|
|
return NULL;
|
|
|
|
ret = (char*) vj_malloc(sizeof(char) * len );
|
|
if(ret == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
int err = vevo_property_get( port, key, 0, &ret );
|
|
if( err != VEVO_NO_ERROR ) {
|
|
if(ret) free(ret);
|
|
return NULL;
|
|
}
|
|
//@ string stored in utf8
|
|
//n if( at == VEVO_ATOM_TYPE_UTF8STRING ) {
|
|
// gsize in,out;
|
|
// gchar *lcstr = g_locale_from_utf8( ret, len, &in, &out, NULL );
|
|
// free(ret);
|
|
// return lcstr;
|
|
// }
|
|
|
|
return ret;
|
|
}
|
|
|
|
char *vevo_property_get_utf8string( void *port, const char *key )
|
|
{
|
|
/* size_t len = vevo_property_element_size( port, key ,0);
|
|
char *ret = NULL;
|
|
if(len<=0) return NULL;
|
|
|
|
if( vevo_property_get( port, key,0,NULL ) != VEVO_NO_ERROR )
|
|
return NULL;
|
|
|
|
int at = vevo_property_atom_type(port,key);
|
|
|
|
ret = (char*) vj_malloc(sizeof(char) * len );
|
|
vevo_property_get( port, key, 0, &ret );
|
|
|
|
if( at == VEVO_ATOM_TYPE_STRING )
|
|
{
|
|
gsize in = 0;
|
|
gsize out = 0;
|
|
gchar *utf8_str = g_locale_to_utf8( (const gchar*) ret, len, &in, &out, NULL );
|
|
free(ret);
|
|
return (char*) utf8_str;
|
|
|
|
}
|
|
return ret; */
|
|
return NULL;
|
|
}
|
|
|
|
char **vevo_property_get_string_arr( vevo_port_t *p, const char *key )
|
|
{
|
|
int n = vevo_property_num_elements( p, key );
|
|
if( n == 0 )
|
|
return NULL;
|
|
char **retval = vj_malloc(sizeof(char*) * n );
|
|
if( retval == NULL )
|
|
return NULL;
|
|
int i;
|
|
for( i = 0; i < n ; i ++ ) {
|
|
retval[i] = vj_calloc( vevo_property_element_size(p,key,i) + 1 );
|
|
int err = vevo_property_get( p, key, i, &retval[i] );
|
|
if( err != VEVO_NO_ERROR ) {
|
|
for( -- i; i >= 0; i -- ) {
|
|
free( retval[i] );
|
|
}
|
|
free(retval);
|
|
return NULL;
|
|
}
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
int
|
|
vevo_property_del(vevo_port_t * p,
|
|
const char *key )
|
|
{
|
|
__vevo_port_t *port = (__vevo_port_t *) p;
|
|
|
|
//@ find value in hash and release from pool
|
|
|
|
ukey_t hash_key = hash_key_code(key);
|
|
// if( port->index == NULL )
|
|
// return VEVO_NO_ERROR;
|
|
|
|
//@ find cached hash key in index
|
|
|
|
port_index_t *head = port->index;
|
|
port_index_t *tmp = head;
|
|
port_index_t *prev = NULL;
|
|
|
|
while( tmp != NULL ) {
|
|
ukey_t idxkey = hash_key_code( tmp->key );
|
|
if( idxkey == hash_key )
|
|
break;
|
|
|
|
prev = tmp;
|
|
tmp = tmp->next;
|
|
}
|
|
|
|
if( tmp != NULL ) {
|
|
if( tmp->hash_code == hash_key ) {
|
|
if( prev )
|
|
prev->next = tmp->next;
|
|
else
|
|
port->index = tmp->next;
|
|
|
|
port_node_free(port, tmp );
|
|
}
|
|
}
|
|
|
|
if(port->list) {
|
|
vevo_property_t *tmp = port->list;
|
|
vevo_property_t *prev = NULL;
|
|
while (tmp != NULL) {
|
|
if( tmp->key == hash_key )
|
|
break;
|
|
prev = tmp;
|
|
tmp = tmp->next;
|
|
}
|
|
if( tmp != NULL ) {
|
|
if( tmp->key == hash_key ) {
|
|
if( prev )
|
|
prev->next = tmp->next;
|
|
else
|
|
port->list = tmp->next;
|
|
|
|
tmp->key = 0;
|
|
|
|
if(!port->table) {
|
|
vevo_free_storage( port, tmp->st );
|
|
prop_node_free( port, tmp );
|
|
}
|
|
else {
|
|
hnode_t *old_node = NULL;
|
|
if ((old_node = property_exists(port, hash_key)) != NULL) {
|
|
vevo_storage_t *oldstor = (vevo_storage_t *) hnode_get(old_node);
|
|
vevo_free_storage(port,oldstor);
|
|
hash_delete((hash_t *) port->table, old_node);
|
|
hnode_destroy(old_node);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return VEVO_ERROR_NOSUCH_PROPERTY;
|
|
}
|
|
|
|
char *vevo_tabs( int lvl ) {
|
|
char tmp[32];
|
|
int i;
|
|
if( lvl > 31 )
|
|
lvl = 31;
|
|
for( i = 0; i < lvl; i ++ )
|
|
tmp[i] = '\t';
|
|
tmp[lvl] = '\0';
|
|
return vj_strdup(tmp);
|
|
}
|
|
|
|
void vevo_port_dump( void *p, int lvl )
|
|
{
|
|
char **keys = vevo_list_properties(p);
|
|
int k;
|
|
|
|
if( keys == NULL ) {
|
|
veejay_msg(0, "Port %p is empty",p);
|
|
return;
|
|
}
|
|
|
|
void *voidval = NULL;
|
|
char *value = NULL;
|
|
int err = 0;
|
|
|
|
char *tabs = NULL;
|
|
if( lvl > 0 )
|
|
tabs = vevo_tabs( lvl );
|
|
|
|
veejay_msg( VEEJAY_MSG_DEBUG, "%s%p", (tabs == NULL ? "/" : tabs ), p );
|
|
|
|
for( k = 0; keys[k] != NULL; k ++ ) {
|
|
int at = vevo_property_atom_type(p,keys[k]);
|
|
switch(at) {
|
|
case VEVO_ATOM_TYPE_PORTPTR:
|
|
err = vevo_property_get(p, keys[k], 0, &voidval );
|
|
if( err == VEVO_NO_ERROR ) {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s %s:",
|
|
(tabs == NULL ? "->" : tabs ), keys[k]);
|
|
vevo_port_dump(voidval, lvl + 1);
|
|
} else {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s error code %d",
|
|
keys[k], err );
|
|
}
|
|
break;
|
|
case VEVO_ATOM_TYPE_VOIDPTR:
|
|
err = vevo_property_get( p, keys[k], 0, &voidval );
|
|
if( err == VEVO_NO_ERROR ) {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s %s VOID*",
|
|
(tabs==NULL ? "->" : tabs ), keys[k]);
|
|
} else {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s %s error code %d",
|
|
(tabs==NULL ? "->" : tabs ), keys[k],err);
|
|
}
|
|
break;
|
|
default:
|
|
value = vevo_sprintf_property_value( p, keys[k] );
|
|
if( value == NULL ) {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s %s no value",
|
|
(tabs == NULL ? "->" : tabs), keys[k] );
|
|
} else {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "%s %s (%d elements) %s",
|
|
(tabs == NULL ? "->" : tabs ), keys[k],
|
|
vevo_property_num_elements( p,keys[k]),
|
|
value );
|
|
free(value);
|
|
}
|
|
break;
|
|
}
|
|
free(keys[k]);
|
|
}
|
|
if(tabs) free(tabs);
|
|
free(keys);
|
|
}
|
|
|
|
int vevo_property_clone( void *port, void *to_port, const char *key, const char *as_key )
|
|
{
|
|
const int n = vevo_property_num_elements(port, key);
|
|
const int t = vevo_property_atom_type( port, key );
|
|
int i;
|
|
if( n <= 0 ) {
|
|
if( n == 0 )
|
|
return VEVO_ERROR_PROPERTY_EMPTY;
|
|
return VEVO_ERROR_NOSUCH_ELEMENT;
|
|
}
|
|
|
|
switch(t) {
|
|
case VEVO_ATOM_TYPE_INT:
|
|
case VEVO_ATOM_TYPE_BOOL:
|
|
{
|
|
int32_t *tmp = (int32_t*) vj_malloc(sizeof(int32_t) * n );
|
|
for(i = 0; i < n; i ++ ) {
|
|
if( vevo_property_get( port, key, i, &(tmp[i])) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_NOSUCH_ELEMENT;
|
|
}
|
|
}
|
|
if( n > 0 ) {
|
|
if( vevo_property_set( to_port, as_key, t, n, tmp ) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_MEMORY_ALLOCATION;
|
|
}
|
|
} else if (n == 0 ) {
|
|
vevo_property_set( to_port, as_key, t, 0, NULL );
|
|
}
|
|
free(tmp);
|
|
}
|
|
break;
|
|
case VEVO_ATOM_TYPE_DOUBLE:
|
|
{
|
|
double *tmp = (double*) vj_malloc(sizeof(double) * n );
|
|
for(i = 0; i < n; i ++ ) {
|
|
if( vevo_property_get( port, key, i, &(tmp[i])) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_NOSUCH_ELEMENT;
|
|
}
|
|
}
|
|
|
|
if( n > 0 ) {
|
|
if( vevo_property_set( to_port, as_key, t, n, tmp ) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_MEMORY_ALLOCATION;
|
|
}
|
|
} else if ( n == 0 ) {
|
|
vevo_property_set(to_port, as_key, t, 0, NULL );
|
|
}
|
|
free(tmp);
|
|
}
|
|
break;
|
|
case VEVO_ATOM_TYPE_UINT64:
|
|
{
|
|
uint64_t *tmp = (uint64_t*) vj_malloc(sizeof(uint64_t) * n );
|
|
for(i = 0; i < n; i ++ ) {
|
|
if( vevo_property_get( port, key, i, &(tmp[i])) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_NOSUCH_ELEMENT;
|
|
}
|
|
}
|
|
|
|
if( n > 0 ) {
|
|
if( vevo_property_set( to_port, as_key, t, n, tmp ) != VEVO_NO_ERROR ) {
|
|
free(tmp);
|
|
return VEVO_ERROR_MEMORY_ALLOCATION;
|
|
}
|
|
} else if ( n == 0 ) {
|
|
vevo_property_set(to_port, as_key, t, 0, NULL );
|
|
}
|
|
free(tmp);
|
|
}
|
|
break;
|
|
|
|
case VEVO_ATOM_TYPE_STRING:
|
|
case VEVO_ATOM_TYPE_UTF8STRING:
|
|
{
|
|
if( n == 1 ) {
|
|
char *src = vevo_property_get_string( port, key );
|
|
if( vevo_property_set(to_port, as_key, t, 1,&src ) != VEVO_NO_ERROR ) {
|
|
free(src);
|
|
return VEVO_ERROR_MEMORY_ALLOCATION;
|
|
}
|
|
}
|
|
else if ( n == 0 ) {
|
|
if( vevo_property_set(to_port,as_key,t,0,NULL ) != VEVO_NO_ERROR ) {
|
|
return VEVO_ERROR_PROPERTY_EMPTY;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
return VEVO_NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
void vevo_dom_dump( void *p, FILE *file )
|
|
{
|
|
char **keys = vevo_list_properties(p);
|
|
int k;
|
|
|
|
if( keys == NULL ) {
|
|
veejay_msg(0, "Port %p is empty",p);
|
|
return;
|
|
}
|
|
|
|
void *voidval = NULL;
|
|
char *value = NULL;
|
|
int err = 0;
|
|
|
|
char *tabs = NULL;
|
|
|
|
if( lvl == 0 || file == NULL ) {
|
|
file = fopen( "rw" ,"/tmp/port1.xml" );
|
|
}
|
|
|
|
for( k = 0; keys[k] != NULL; k ++ ) {
|
|
if( strncasecmp( keys[k], "type",4 ) == 0 ) {
|
|
int tval = 0;
|
|
err = vevo_property_get( p, keys[k],0,&tval );
|
|
fprintf( file,"<p>%s</p>", vevo_identify_port(tval));
|
|
continue;
|
|
}
|
|
|
|
int at = vevo_property_atom_type(p,keys[k]);
|
|
switch(at) {
|
|
case VEVO_ATOM_TYPE_PORTPTR:
|
|
err = vevo_property_get(p, keys[k], 0, &voidval );
|
|
if( err == VEVO_NO_ERROR ) {
|
|
fprintf(file,"<ul><li>%s</li>", keys[k] );
|
|
vevo_dom_dump(voidval, file);
|
|
fprintf(file,"</ul>");
|
|
} else {
|
|
fprintf(file,"<ul><li>%s with error %s</li>", keys[k] );
|
|
}
|
|
break;
|
|
case VEVO_ATOM_TYPE_VOIDPTR:
|
|
err = vevo_property_get( p, keys[k], 0, &voidval );
|
|
if( err == VEVO_NO_ERROR ) {
|
|
fprintf( file, "<li><b>private</b></li>");
|
|
|
|
} else {
|
|
fprintf( file, "<li><b>private with error %s</b></li>",keys[k]);
|
|
}
|
|
break;
|
|
default:
|
|
value = vevo_sprintf_property_value( p, keys[k] );
|
|
fpritnf( file, "<li><table><tr><td>%s</td><td>%s</td></tr></table></li>",keys[k],value);
|
|
break;
|
|
}
|
|
free(keys[k]);
|
|
}
|
|
if(tabs) free(tabs);
|
|
free(keys);
|
|
|
|
if( lvl == 0 )
|
|
fclose(file);
|
|
}*/
|
|
|
|
|
|
int vevo_write_xml( vevo_port_t *root, const char *destination, char *hiearchy[] )
|
|
{
|
|
char **properties = vevo_list_properties( root );
|
|
if( properties == NULL )
|
|
return 0;
|
|
/* xmlNodePtr childnode;
|
|
xmlDocPtr doc = xmlNewDoc( "1.0" );
|
|
xmlNodePtr rootnode =
|
|
xmlNewDocNode( doc, NULL , (const xmlChar*) hiearchy[0], NULL );
|
|
xmlDocSetRootElement( doc, rootnode );
|
|
|
|
int i = 0;
|
|
int level = 1;
|
|
while( properties[i] != NULL )
|
|
{
|
|
int atom_type = vevo_property_atom_type( root, properties[i] );
|
|
void *port = NULL;
|
|
|
|
childnode = xmlNewChild( rootnode, NULL, (const xmlChar*)
|
|
hierachy[ level ], NULL );
|
|
vevo_property_get( port, properties[i], 0, &port );
|
|
|
|
|
|
i++;
|
|
}
|
|
|
|
xmlNodePtr childnode = xmlNewChild( rootnode, NULL, (const xmlChar*) "timeline", NULL );
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|