summaryrefslogtreecommitdiffstats
path: root/libhb/hb_dict.c
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2015-03-09 15:05:47 +0000
committerjstebbins <[email protected]>2015-03-09 15:05:47 +0000
commit9e9e47cd1913a34bd248a3ac5a8da9765e638bdc (patch)
tree8350a5991ef036fe05d6d7903dfd0603a3a05f78 /libhb/hb_dict.c
parent44eb2602873819fcb35cc92ea53a8f14e5bc7c64 (diff)
libhb: use jansson for hb_dict
This paves the way to doing preset processing in libhb. Initially for the CLI but other frontends may benefit eventually. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6981 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/hb_dict.c')
-rw-r--r--libhb/hb_dict.c620
1 files changed, 481 insertions, 139 deletions
diff --git a/libhb/hb_dict.c b/libhb/hb_dict.c
index 48d5c6a01..d8bbc8713 100644
--- a/libhb/hb_dict.c
+++ b/libhb/hb_dict.c
@@ -10,219 +10,561 @@
#include "hb.h"
#include "hb_dict.h"
-hb_dict_t * hb_dict_init( int alloc )
+hb_value_type_t hb_value_type(const hb_value_t *value)
{
- hb_dict_t * dict = NULL;
- dict = malloc( sizeof( hb_dict_t ) );
- if( !dict )
+ if (value == NULL)
+ return HB_VALUE_TYPE_NULL;
+ hb_value_type_t type = json_typeof(value);
+ if (type == JSON_TRUE || type == JSON_FALSE)
+ return HB_VALUE_TYPE_BOOL;
+ return type;
+}
+
+hb_value_t * hb_value_dup(hb_value_t *value)
+{
+ if (value == NULL) return NULL;
+ return json_deep_copy(value);
+}
+
+void hb_value_incref(hb_value_t *value)
+{
+ if (value == NULL) return;
+ json_incref(value);
+}
+
+void hb_value_decref(hb_value_t *value)
+{
+ if (value == NULL) return;
+ json_decref(value);
+}
+
+void hb_value_free(hb_value_t **_value)
+{
+ hb_value_decref(*_value);
+ *_value = NULL;
+}
+
+hb_value_t * hb_value_string(const char * value)
+{
+ // json_string does not create a value for NULL strings.
+ // So create JSON_NULL in this case
+ if (value == NULL)
+ return json_null();
+ return json_string(value);
+}
+
+hb_value_t * hb_value_int(json_int_t value)
+{
+ return json_integer(value);
+}
+
+hb_value_t * hb_value_double(double value)
+{
+ return json_real(value);
+}
+
+hb_value_t * hb_value_bool(int value)
+{
+ return json_boolean(value);
+}
+
+static hb_value_t* xform_null(hb_value_type_t type)
+{
+ switch (type)
{
- hb_log( "ERROR: could not allocate hb_dict_t" );
- return NULL;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_false();
+ case HB_VALUE_TYPE_INT:
+ return json_integer(0);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(0.0);
+ case HB_VALUE_TYPE_STRING:
+ return json_null();
}
- dict->count = 0;
- dict->objects = malloc( alloc * sizeof( hb_dict_entry_t ) );
- if( !dict->objects )
+}
+
+static hb_value_t* xform_bool(const hb_value_t *value, hb_value_type_t type)
+{
+ json_int_t b = json_is_true(value);
+ switch (type)
{
- hb_log( "ERROR: could not allocate hb_dict_t objects" );
- dict->alloc = 0;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean(b);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(b);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(b);
+ case HB_VALUE_TYPE_STRING:
+ {
+ char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, b);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
+ }
}
- else
+}
+
+static hb_value_t* xform_int(const hb_value_t *value, hb_value_type_t type)
+{
+ json_int_t i = json_integer_value(value);
+ switch (type)
{
- dict->alloc = alloc;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean(i);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(i);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(i);
+ case HB_VALUE_TYPE_STRING:
+ {
+ char *s = hb_strdup_printf("%"JSON_INTEGER_FORMAT, i);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
+ }
}
- return dict;
}
-void hb_dict_free( hb_dict_t ** dict_ptr )
+static hb_value_t* xform_double(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( dict )
+ double d = json_real_value(value);
+ switch (type)
{
- if( dict->objects )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ return json_null();
+ case HB_VALUE_TYPE_BOOL:
+ return json_boolean((int)d != 0);
+ case HB_VALUE_TYPE_INT:
+ return json_integer(d);
+ case HB_VALUE_TYPE_DOUBLE:
+ return json_real(d);
+ case HB_VALUE_TYPE_STRING:
{
- int i;
- for( i = 0; i < dict->count; i++ )
- {
- if( dict->objects[i].key )
- {
- free( dict->objects[i].key );
- }
- if( dict->objects[i].value )
- {
- free( dict->objects[i].value );
- }
- }
- free( dict->objects );
+ char *s = hb_strdup_printf("%g", d);
+ hb_value_t *v = json_string(s);
+ free(s);
+ return v;
}
- free( *dict_ptr );
- *dict_ptr = NULL;
}
}
-void hb_dict_set( hb_dict_t ** dict_ptr, const char * key, const char * value )
+static hb_value_t* xform_string(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( !dict )
+ const char *s = json_string_value(value);
+ switch (type)
{
- hb_log( "hb_dict_set: NULL dictionary" );
- return;
+ default:
+ case HB_VALUE_TYPE_NULL:
+ {
+ return json_null();
+ }
+ case HB_VALUE_TYPE_BOOL:
+ {
+ if (s != NULL &&
+ (!strcasecmp(s, "true") ||
+ !strcasecmp(s, "yes") ||
+ !strcasecmp(s, "1")))
+ {
+ return json_true();
+ }
+ return json_false();
+ }
+ case HB_VALUE_TYPE_INT:
+ {
+ json_int_t i = 0;
+ if (s != NULL)
+ strtoll(s, NULL, 0);
+ return json_integer(i);
+ }
+ case HB_VALUE_TYPE_DOUBLE:
+ {
+ double d = 0.0;
+ if (s != NULL)
+ d = strtod(s, NULL);
+ return json_real(d);
+ }
+ case HB_VALUE_TYPE_STRING:
+ {
+ return json_string(s);
+ }
}
- if( !key || !strlen( key ) )
- return;
- hb_dict_entry_t * entry = hb_dict_get( dict, key );
- if( entry )
+}
+
+static hb_value_t* xform_array(const hb_value_t *value, hb_value_type_t type)
+{
+ hb_value_t *first = NULL;
+ int count = hb_value_array_len(value);
+
+ if (count > 0)
+ first = hb_value_array_get(value, 0);
+ switch (type)
{
- if( entry->value )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ case HB_VALUE_TYPE_BOOL:
+ case HB_VALUE_TYPE_INT:
+ case HB_VALUE_TYPE_DOUBLE:
+ return hb_value_xform(first, type);
+ case HB_VALUE_TYPE_STRING:
{
- if( value && !strcmp( value, entry->value ) )
- return;
+ char *r = strdup("");
+ int ii;
+ for (ii = 0; ii < count; ii++)
+ {
+ hb_value_t *v = hb_value_array_get(value, ii);
+ hb_value_t *x = hb_value_xform(v, type);
+ const char *s = hb_value_get_string(x);
+ if (s != NULL)
+ {
+ char *tmp = r;
+ r = hb_strdup_printf("%s%s,", tmp, s);
+ free(tmp);
+ }
+ hb_value_free(&x);
+ }
+ int len = strlen(r);
+ hb_value_t *v;
+ if (len > 0)
+ {
+ // Removing trailing ','
+ r[len - 1] = 0;
+ v = json_string(r);
+ }
else
{
- free( entry->value );
- entry->value = NULL;
+ free(r);
+ r = NULL;
+ v = json_null();
}
+ free(r);
+ return v;
}
- if( value && strlen( value ) )
- entry->value = strdup( value );
}
- else
+}
+
+static hb_value_t* xform_dict(const hb_value_t *dict, hb_value_type_t type)
+{
+ hb_value_t *first = NULL;
+ hb_dict_iter_t iter = hb_dict_iter_init(dict);
+
+ if (iter != HB_DICT_ITER_DONE)
+ first = hb_dict_iter_value(iter);
+
+ switch (type)
{
- if( dict->alloc <= dict->count )
+ default:
+ case HB_VALUE_TYPE_NULL:
+ case HB_VALUE_TYPE_BOOL:
+ case HB_VALUE_TYPE_INT:
+ case HB_VALUE_TYPE_DOUBLE:
+ return hb_value_xform(first, type);
+ case HB_VALUE_TYPE_STRING:
{
- hb_dict_entry_t * tmp = NULL;
- tmp = malloc( ( 2 * dict->alloc ) * sizeof( hb_dict_entry_t ) );
- if( !tmp )
+ char *r = strdup("");
+ hb_dict_iter_t iter;
+ for (iter = hb_dict_iter_init(dict);
+ iter != HB_DICT_ITER_DONE;
+ iter = hb_dict_iter_next(dict, iter))
+ {
+ const char *k = hb_dict_iter_key(iter);
+ hb_value_t *v = hb_dict_iter_value(iter);
+ hb_value_t *x = hb_value_xform(v, type);
+ const char *s = hb_value_get_string(x);
+
+ char *tmp = r;
+ r = hb_strdup_printf("%s%s%s%s:",
+ r,
+ k,
+ s ? "=" : "",
+ s ? s : "");
+ free(tmp);
+ hb_value_free(&x);
+ }
+ int len = strlen(r);
+ hb_value_t *v;
+ if (len > 0)
{
- hb_log( "ERROR: could not realloc hb_dict_t objects" );
- return;
+ // Removing trailing ':'
+ r[len - 1] = 0;
+ v = json_string(r);
}
- if( dict->objects )
+ else
{
- if( dict->count )
- memcpy( tmp, dict->objects, dict->count * sizeof( hb_dict_entry_t ) );
- free( dict->objects );
+ free(r);
+ r = NULL;
+ v = json_null();
}
- dict->objects = tmp;
- dict->alloc *= 2;
- }
- dict->objects[dict->count].key = strdup( key );
- if( value && strlen( value ) )
- dict->objects[dict->count].value = strdup( value );
- else
- dict->objects[dict->count].value = NULL;
- dict->count++;
+ free(r);
+ return v;
+ }
}
}
-void hb_dict_unset( hb_dict_t ** dict_ptr, const char * key )
+hb_value_t* hb_value_xform(const hb_value_t *value, hb_value_type_t type)
{
- hb_dict_t * dict = *dict_ptr;
- if( !dict || !dict->objects || !key || !strlen( key ) )
- return;
- int i;
- for( i = 0; i < dict->count; i++ )
- if( !strcmp( key, dict->objects[i].key ) )
+ hb_value_type_t src_type = hb_value_type(value);
+ if (src_type == type && value != NULL)
+ {
+ json_incref((hb_value_t*)value);
+ return (hb_value_t*)value;
+ }
+ switch (src_type)
+ {
+ default:
+ case HB_VALUE_TYPE_NULL:
+ {
+ return xform_null(type);
+ }
+ case HB_VALUE_TYPE_BOOL:
+ {
+ return xform_bool(value, type);
+ }
+ case HB_VALUE_TYPE_INT:
{
- free( dict->objects[i].key );
- if( dict->objects[i].value )
- free( dict->objects[i].value );
- if( i != --dict->count )
- memmove( &dict->objects[i], &dict->objects[i+1],
- sizeof( hb_dict_entry_t ) * ( dict->count - i ) );
+ return xform_int(value, type);
}
+ case HB_VALUE_TYPE_DOUBLE:
+ {
+ return xform_double(value, type);
+ }
+ case HB_VALUE_TYPE_STRING:
+ {
+ return xform_string(value, type);
+ }
+ case HB_VALUE_TYPE_ARRAY:
+ {
+ return xform_array(value, type);
+ }
+ case HB_VALUE_TYPE_DICT:
+ {
+ return xform_dict(value, type);
+ }
+ }
}
-hb_dict_entry_t * hb_dict_get( hb_dict_t * dict, const char * key )
+const char * hb_value_get_string(const hb_value_t *value)
{
- if( !dict || !dict->objects || !key || !strlen( key ) )
- return NULL;
- int i;
- for( i = 0; i < dict->count; i++ )
- if( !strcmp( key, dict->objects[i].key ) )
- return &dict->objects[i];
- return NULL;
+ if (hb_value_type(value) != HB_VALUE_TYPE_STRING) return NULL;
+ return json_string_value(value);
+}
+
+json_int_t hb_value_get_int(const hb_value_t *value)
+{
+ json_int_t result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_INT);
+ result = json_integer_value(v);
+ json_decref(v);
+ return result;
+}
+
+double hb_value_get_double(const hb_value_t *value)
+{
+ double result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_DOUBLE);
+ result = json_real_value(v);
+ json_decref(v);
+ return result;
}
-hb_dict_entry_t * hb_dict_next( hb_dict_t * dict, hb_dict_entry_t * previous )
+int hb_value_get_bool(const hb_value_t *value)
{
- if( dict == NULL || dict->objects == NULL || !dict->count )
+ int result;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_BOOL);
+ result = json_is_true(v);
+ json_decref(v);
+ return result;
+}
+
+char*
+hb_value_get_string_xform(const hb_value_t *value)
+{
+ char *result;
+ if (hb_value_type(value) == HB_VALUE_TYPE_NULL)
+ return NULL;
+ hb_value_t *v = hb_value_xform(value, HB_VALUE_TYPE_STRING);
+ if (hb_value_type(v) == HB_VALUE_TYPE_NULL)
return NULL;
- if( previous == NULL )
- return &dict->objects[0];
- unsigned int prev_index = previous - dict->objects;
- if( prev_index + 1 < dict->count )
- return &dict->objects[prev_index+1];
- return NULL;
+ result = strdup(json_string_value(v));
+ json_decref(v);
+ return result;
+}
+
+void hb_dict_free(hb_dict_t **_dict)
+{
+ hb_value_free(_dict);
+}
+
+hb_dict_t * hb_dict_init()
+{
+ return json_object();
+}
+
+void hb_dict_set(hb_dict_t * dict, const char *key, hb_value_t *value)
+{
+ json_object_set_new(dict, key, value);
+}
+
+int hb_dict_remove(hb_dict_t * dict, const char * key)
+{
+ return json_object_del(dict, key) == 0;
+}
+
+hb_value_t * hb_dict_get(hb_dict_t * dict, const char * key)
+{
+ return json_object_get(dict, key);
+}
+
+hb_dict_iter_t hb_dict_iter_init(const hb_dict_t *dict)
+{
+ if (dict == NULL)
+ return HB_DICT_ITER_DONE;
+ return json_object_iter((hb_dict_t*)dict);
+}
+
+hb_dict_iter_t hb_dict_iter_next(const hb_dict_t *dict, hb_dict_iter_t iter)
+{
+ return json_object_iter_next((hb_dict_t*)dict, iter);
+}
+
+const char * hb_dict_iter_key(const hb_dict_iter_t iter)
+{
+ return json_object_iter_key(iter);
}
-hb_dict_t * hb_encopts_to_dict( const char * encopts, int encoder )
+hb_value_t * hb_dict_iter_value(const hb_dict_iter_t iter)
+{
+ return json_object_iter_value(iter);
+}
+
+hb_value_array_t*
+hb_value_array_init()
+{
+ return json_array();
+}
+
+void
+hb_value_array_clear(hb_value_array_t *array)
+{
+ json_array_clear(array);
+}
+
+hb_value_t*
+hb_value_array_get(const hb_value_array_t *array, int index)
+{
+ return json_array_get(array, index);
+}
+
+void
+hb_value_array_set(hb_value_array_t *array, int index, hb_value_t *value)
+{
+ if (index < 0 || index >= json_array_size(array))
+ {
+ hb_error("hb_value_array_set: invalid index %d size %zu",
+ index, json_array_size(array));
+ return;
+ }
+ json_array_set_new(array, index, value);
+}
+
+void
+hb_value_array_insert(hb_value_array_t *array, int index, hb_value_t *value)
+{
+ json_array_insert_new(array, index, value);
+}
+
+void
+hb_value_array_append(hb_value_array_t *array, hb_value_t *value)
+{
+ json_array_append_new(array, value);
+}
+
+void
+hb_value_array_remove(hb_value_array_t *array, int index)
+{
+ json_array_remove(array, index);
+}
+
+void
+hb_value_array_copy(hb_value_array_t *dst,
+ const hb_value_array_t *src, int count)
+{
+ size_t len;
+ int ii;
+
+ // empty the first array if it is not already empty
+ json_array_clear(dst);
+
+ len = hb_value_array_len(src);
+ count = MIN(count, len);
+ for (ii = 0; ii < count; ii++)
+ hb_value_array_append(dst, hb_value_dup(hb_value_array_get(src, ii)));
+}
+
+size_t
+hb_value_array_len(const hb_value_array_t *array)
+{
+ return json_array_size(array);
+}
+
+hb_dict_t * hb_encopts_to_dict(const char * encopts, int encoder)
{
hb_dict_t * dict = NULL;
- if( encopts && *encopts )
+
+ if (encopts && *encopts)
{
char *cur_opt, *opts_start, *value;
const char *name;
- dict = hb_dict_init( 10 );
+ dict = hb_dict_init();
if( !dict )
return NULL;
- cur_opt = opts_start = strdup( encopts );
- if( opts_start )
+ cur_opt = opts_start = strdup(encopts);
+ if (opts_start)
{
- while( *cur_opt )
+ while (*cur_opt)
{
name = cur_opt;
- cur_opt += strcspn( cur_opt, ":" );
- if( *cur_opt )
+ cur_opt += strcspn(cur_opt, ":");
+ if (*cur_opt)
{
*cur_opt = 0;
cur_opt++;
}
- value = strchr( name, '=' );
- if( value )
+ value = strchr(name, '=');
+ if (value)
{
*value = 0;
value++;
}
// x264 has multiple names for some options
- if( encoder == HB_VCODEC_X264 )
- name = hb_x264_encopt_name( name );
+ if (encoder == HB_VCODEC_X264)
+ name = hb_x264_encopt_name(name);
#ifdef USE_X265
// x265 has multiple names for some options
- if( encoder == HB_VCODEC_X265 )
- name = hb_x265_encopt_name( name );
+ if (encoder == HB_VCODEC_X265)
+ name = hb_x265_encopt_name(name);
#endif
- hb_dict_set( &dict, name, value );
+ if (name != NULL)
+ {
+ hb_dict_set(dict, name, hb_value_string(value));
+ }
}
}
- free( opts_start );
+ free(opts_start);
}
return dict;
}
-char * hb_dict_to_encopts( hb_dict_t * dict )
+char * hb_dict_to_encopts(const hb_dict_t * dict)
{
- int first_opt = 1;
- char *tmp, *encopts_tmp, *encopts = NULL;
- hb_dict_entry_t * entry = NULL;
- while( ( entry = hb_dict_next( dict, entry ) ) )
- {
- tmp = hb_strdup_printf( "%s%s%s%s",
- first_opt ? "" : ":",
- entry->key,
- entry->value ? "=" : "",
- entry->value ? entry->value : "" );
- if( tmp )
- {
- encopts_tmp = hb_strncat_dup( encopts, tmp, strlen( tmp ) );
- if( encopts_tmp )
- {
- if( encopts )
- free( encopts );
- encopts = encopts_tmp;
- }
- first_opt = 0;
- free( tmp );
- }
- }
- return encopts;
+ return hb_value_get_string_xform(dict);
}