diff options
author | jstebbins <[email protected]> | 2015-03-09 15:05:47 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2015-03-09 15:05:47 +0000 |
commit | 9e9e47cd1913a34bd248a3ac5a8da9765e638bdc (patch) | |
tree | 8350a5991ef036fe05d6d7903dfd0603a3a05f78 /libhb/hb_dict.c | |
parent | 44eb2602873819fcb35cc92ea53a8f14e5bc7c64 (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.c | 620 |
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); } |