diff options
Diffstat (limited to 'libs/cairo-1.16.0/util/cairo-script/cairo-script-objects.c')
-rw-r--r-- | libs/cairo-1.16.0/util/cairo-script/cairo-script-objects.c | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/libs/cairo-1.16.0/util/cairo-script/cairo-script-objects.c b/libs/cairo-1.16.0/util/cairo-script/cairo-script-objects.c new file mode 100644 index 0000000..2d7937b --- /dev/null +++ b/libs/cairo-1.16.0/util/cairo-script/cairo-script-objects.c @@ -0,0 +1,938 @@ +/* + * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Chris Wilson. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "config.h" + +#include "cairo-script-private.h" + +#include <limits.h> /* INT_MAX */ +#include <string.h> + +csi_status_t +csi_array_new (csi_t *ctx, + csi_integer_t initial_size, + csi_object_t *obj) + +{ + csi_array_t *array; + + if (ctx->free_array == NULL || + ctx->free_array->stack.size <= initial_size) + { + csi_status_t status; + + array = _csi_slab_alloc (ctx, sizeof (csi_array_t)); + if (_csi_unlikely (array == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + status = _csi_stack_init (ctx, &array->stack, + initial_size ? initial_size : 32); + if (_csi_unlikely (status)) { + _csi_slab_free (ctx, array, sizeof (csi_array_t)); + return status; + } + } else { + array = ctx->free_array; + ctx->free_array = NULL; + } + + array->base.type = CSI_OBJECT_TYPE_ARRAY; + array->base.ref = 1; + + obj->type = CSI_OBJECT_TYPE_ARRAY; + obj->datum.array = array; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_array_put (csi_t *ctx, + csi_array_t *array, + csi_integer_t elem, + csi_object_t *value) +{ + if (_csi_unlikely (elem < 0)) + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + + if (_csi_unlikely (elem >= array->stack.len)) { + csi_status_t status; + + status = _csi_stack_grow (ctx, &array->stack, elem + 1); + if (_csi_unlikely (status)) + return status; + + memset (array->stack.objects + array->stack.len, + 0, (elem - array->stack.len + 1) * sizeof (csi_object_t)); + array->stack.len = elem + 1; + } + + csi_object_free (ctx, &array->stack.objects[elem]); + array->stack.objects[elem] = *csi_object_reference (value); + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_array_get (csi_t *ctx, + csi_array_t *array, + csi_integer_t elem, + csi_object_t *value) +{ + if (_csi_unlikely (elem < 0)) + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + + if (_csi_unlikely (elem > array->stack.len)) + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + + *value = array->stack.objects[elem]; + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_array_append (csi_t *ctx, + csi_array_t *array, + csi_object_t *obj) +{ + return _csi_stack_push (ctx, &array->stack, csi_object_reference (obj)); +} + +inline csi_status_t +_csi_array_execute (csi_t *ctx, csi_array_t *array) +{ + csi_integer_t i; + csi_status_t status; + + if (_csi_unlikely (array->stack.len == 0)) + return CSI_STATUS_SUCCESS; + + for (i = 0; i < array->stack.len; i++) { + csi_object_t *obj = &array->stack.objects[i]; + + if (obj->type & CSI_OBJECT_ATTR_EXECUTABLE) { + if (obj->type == (CSI_OBJECT_TYPE_ARRAY | + CSI_OBJECT_ATTR_EXECUTABLE)) + { + status = _csi_push_ostack_copy (ctx, &array->stack.objects[i]); + } + else + status = csi_object_execute (ctx, &array->stack.objects[i]); + } else + status = _csi_push_ostack_copy (ctx, &array->stack.objects[i]); + if (_csi_unlikely (status)) + return status; + } + + return CSI_STATUS_SUCCESS; +} + +void +csi_array_free (csi_t *ctx, csi_array_t *array) +{ +#if CSI_DEBUG_MALLOC + _csi_stack_fini (ctx, &array->stack); + _csi_slab_free (ctx, array, sizeof (csi_array_t)); +#else + csi_integer_t n; + + for (n = 0; n < array->stack.len; n++) + csi_object_free (ctx, &array->stack.objects[n]); + array->stack.len = 0; + + if (ctx->free_array != NULL) { + if (array->stack.size > ctx->free_array->stack.size) { + csi_array_t *tmp = ctx->free_array; + ctx->free_array = array; + array = tmp; + } + + _csi_stack_fini (ctx, &array->stack); + _csi_slab_free (ctx, array, sizeof (csi_array_t)); + } else + ctx->free_array = array; +#endif +} + +static cairo_bool_t +_dictionary_name_equal (const void *_a, const void *_b) +{ + return TRUE; +} + +csi_status_t +csi_dictionary_new (csi_t *ctx, + csi_object_t *obj) + +{ + csi_dictionary_t *dict; + + if (ctx->free_dictionary != NULL) { + dict = ctx->free_dictionary; + ctx->free_dictionary = NULL; + } else { + csi_status_t status; + + dict = _csi_slab_alloc (ctx, sizeof (csi_dictionary_t)); + if (_csi_unlikely (dict == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + status = _csi_hash_table_init (&dict->hash_table, + _dictionary_name_equal); + if (_csi_unlikely (status)) { + _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t)); + return status; + } + } + + dict->base.type = CSI_OBJECT_TYPE_DICTIONARY; + dict->base.ref = 1; + + obj->type = CSI_OBJECT_TYPE_DICTIONARY; + obj->datum.dictionary = dict; + + return CSI_STATUS_SUCCESS; +} + +struct _dictionary_entry_pluck { + csi_t *ctx; + csi_hash_table_t *hash_table; +}; + +static void +_dictionary_entry_pluck (void *entry, void *data) +{ + csi_dictionary_entry_t *dict_entry; + struct _dictionary_entry_pluck *pluck_data; + + dict_entry = entry; + pluck_data = data; + + _csi_hash_table_remove (pluck_data->hash_table, entry); + csi_object_free (pluck_data->ctx, &dict_entry->value); + _csi_slab_free (pluck_data->ctx, entry, sizeof (csi_dictionary_entry_t)); +} + +void +csi_dictionary_free (csi_t *ctx, + csi_dictionary_t *dict) +{ + struct _dictionary_entry_pluck data; + + data.ctx = ctx; + data.hash_table = &dict->hash_table; + _csi_hash_table_foreach (&dict->hash_table, + _dictionary_entry_pluck, + &data); + +#if CSI_DEBUG_MALLOC + _csi_hash_table_fini (&dict->hash_table); + _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t)); +#else + if (ctx->free_dictionary != NULL) { + _csi_hash_table_fini (&dict->hash_table); + _csi_slab_free (ctx, dict, sizeof (csi_dictionary_t)); + } else + ctx->free_dictionary = dict; +#endif +} + +csi_status_t +csi_dictionary_put (csi_t *ctx, + csi_dictionary_t *dict, + csi_name_t name, + csi_object_t *value) +{ + csi_dictionary_entry_t *entry; + csi_status_t status; + + entry = _csi_hash_table_lookup (&dict->hash_table, + (csi_hash_entry_t *) &name); + if (entry != NULL) { + /* replace the existing entry */ + csi_object_free (ctx, &entry->value); + entry->value = *csi_object_reference (value); + return CSI_STATUS_SUCCESS; + } + + entry = _csi_slab_alloc (ctx, sizeof (*entry)); + if (_csi_unlikely (entry == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + entry->hash_entry.hash = name; + status = _csi_hash_table_insert (&dict->hash_table, &entry->hash_entry); + if (_csi_unlikely (status)) { + _csi_slab_free (ctx, entry, sizeof (*entry)); + return status; + } + + entry->value = *csi_object_reference (value); + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_dictionary_get (csi_t *ctx, + csi_dictionary_t *dict, + csi_name_t name, + csi_object_t *value) +{ + csi_dictionary_entry_t *entry; + + entry = _csi_hash_table_lookup (&dict->hash_table, + (csi_hash_entry_t *) &name); + if (_csi_unlikely (entry == NULL)) + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + + *value = entry->value; + return CSI_STATUS_SUCCESS; +} + +csi_boolean_t +csi_dictionary_has (csi_dictionary_t *dict, + csi_name_t name) +{ + return _csi_hash_table_lookup (&dict->hash_table, + (csi_hash_entry_t *) &name) != NULL; +} + +void +csi_dictionary_remove (csi_t *ctx, + csi_dictionary_t *dict, + csi_name_t name) +{ + csi_dictionary_entry_t *entry; + + entry = _csi_hash_table_lookup (&dict->hash_table, + (csi_hash_entry_t *) &name); + if (entry != NULL) { + _csi_hash_table_remove (&dict->hash_table, &entry->hash_entry); + csi_object_free (ctx, &entry->value); + _csi_slab_free (ctx, entry, sizeof (csi_dictionary_entry_t)); + } +} + +csi_status_t +csi_matrix_new (csi_t *ctx, + csi_object_t *obj) +{ + csi_matrix_t *matrix; + + matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t)); + if (_csi_unlikely (matrix == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + matrix->base.type = CSI_OBJECT_TYPE_MATRIX; + matrix->base.ref = 1; + cairo_matrix_init_identity (&matrix->matrix); + + obj->type = CSI_OBJECT_TYPE_MATRIX; + obj->datum.matrix = matrix; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_matrix_new_from_array (csi_t *ctx, + csi_object_t *obj, + csi_array_t *array) +{ + csi_matrix_t *matrix; + + if (_csi_unlikely (array->stack.len != 6)) + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + + matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t)); + if (_csi_unlikely (matrix == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + matrix->base.type = CSI_OBJECT_TYPE_MATRIX; + matrix->base.ref = 1; + cairo_matrix_init (&matrix->matrix, + csi_number_get_value (&array->stack.objects[0]), + csi_number_get_value (&array->stack.objects[1]), + csi_number_get_value (&array->stack.objects[2]), + csi_number_get_value (&array->stack.objects[3]), + csi_number_get_value (&array->stack.objects[4]), + csi_number_get_value (&array->stack.objects[5])); + + obj->type = CSI_OBJECT_TYPE_MATRIX; + obj->datum.matrix = matrix; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_matrix_new_from_matrix (csi_t *ctx, + csi_object_t *obj, + const cairo_matrix_t *m) +{ + csi_matrix_t *matrix; + + matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t)); + if (_csi_unlikely (matrix == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + matrix->base.type = CSI_OBJECT_TYPE_MATRIX; + matrix->base.ref = 1; + matrix->matrix = *m; + + obj->type = CSI_OBJECT_TYPE_MATRIX; + obj->datum.matrix = matrix; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_matrix_new_from_values (csi_t *ctx, + csi_object_t *obj, + double v[6]) +{ + csi_matrix_t *matrix; + + matrix = _csi_slab_alloc (ctx, sizeof (csi_matrix_t)); + if (_csi_unlikely (matrix == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + matrix->base.type = CSI_OBJECT_TYPE_MATRIX; + matrix->base.ref = 1; + cairo_matrix_init (&matrix->matrix, v[0], v[1], v[2], v[3], v[4], v[5]); + + obj->type = CSI_OBJECT_TYPE_MATRIX; + obj->datum.matrix = matrix; + + return CSI_STATUS_SUCCESS; +} + +void +csi_matrix_free (csi_t *ctx, + csi_matrix_t *obj) +{ + _csi_slab_free (ctx, obj, sizeof (csi_matrix_t)); +} + + +csi_status_t +csi_name_new (csi_t *ctx, + csi_object_t *obj, + const char *str, + int len) +{ + csi_status_t status; + + status = _csi_intern_string (ctx, &str, len); + if (_csi_unlikely (status)) + return status; + + obj->type = CSI_OBJECT_TYPE_NAME; + obj->datum.name = (csi_name_t) str; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_name_new_static (csi_t *ctx, + csi_object_t *obj, + const char *str) +{ + csi_status_t status; + + status = _csi_intern_string (ctx, &str, strlen (str)); + if (_csi_unlikely (status)) + return status; + + obj->type = CSI_OBJECT_TYPE_NAME; + obj->datum.name = (csi_name_t) str; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_string_new (csi_t *ctx, + csi_object_t *obj, + const char *str, + int len) +{ + csi_string_t *string; + + if (len < 0) + len = strlen (str); + if (_csi_unlikely (len >= INT_MAX)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + if (ctx->free_string == NULL || ctx->free_string->len <= len) { + string = _csi_slab_alloc (ctx, sizeof (csi_string_t)); + if (_csi_unlikely (string == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + string->string = _csi_alloc (ctx, len + 1); + if (_csi_unlikely (string->string == NULL)) { + _csi_slab_free (ctx, string, sizeof (csi_string_t)); + return _csi_error (CSI_STATUS_NO_MEMORY); + } + } else { + string = ctx->free_string; + ctx->free_string = NULL; + } + + if (str != NULL) { + memcpy (string->string, str, len); + string->string[len] = '\0'; + } + string->len = len; + string->deflate = 0; + string->method = NONE; + + string->base.type = CSI_OBJECT_TYPE_STRING; + string->base.ref = 1; + + obj->type = CSI_OBJECT_TYPE_STRING; + obj->datum.string = string; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_string_deflate_new (csi_t *ctx, + csi_object_t *obj, + void *bytes, + int in_len, + int out_len) +{ + csi_status_t status; + csi_string_t *string; + + status = csi_string_new (ctx, obj, bytes, in_len); + if (_csi_unlikely (status)) + return status; + + string = obj->datum.string; + string->deflate = out_len; + string->method = ZLIB; + + return CSI_STATUS_SUCCESS; +} + +csi_status_t +csi_string_new_from_bytes (csi_t *ctx, + csi_object_t *obj, + char *bytes, + unsigned int len) +{ + csi_string_t *string; + + if (_csi_unlikely (len >= INT_MAX)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + string = _csi_slab_alloc (ctx, sizeof (csi_string_t)); + if (_csi_unlikely (string == NULL)) + return _csi_error (CSI_STATUS_NO_MEMORY); + + string->string = bytes; + string->len = len; + string->deflate = 0; + string->method = NONE; + + string->base.type = CSI_OBJECT_TYPE_STRING; + string->base.ref = 1; + + obj->type = CSI_OBJECT_TYPE_STRING; + obj->datum.string = string; + + return CSI_STATUS_SUCCESS; +} + +static inline csi_status_t +_csi_string_execute (csi_t *ctx, csi_string_t *string) +{ + csi_status_t status; + csi_object_t obj; + + if (_csi_unlikely (string->len == 0)) + return CSI_STATUS_SUCCESS; + + status = csi_file_new_for_bytes (ctx, &obj, string->string, string->len); + if (_csi_unlikely (status)) + return status; + + status = _csi_scan_file (ctx, obj.datum.file); + csi_object_free (ctx, &obj); + + return status; +} + +void +csi_string_free (csi_t *ctx, csi_string_t *string) +{ +#if CSI_DEBUG_MALLOC + _csi_free (ctx, string->string); + _csi_slab_free (ctx, string, sizeof (csi_string_t)); +#else + if (ctx->free_string != NULL) { + if (string->len > ctx->free_string->len) { + csi_string_t *tmp = ctx->free_string; + ctx->free_string = string; + string = tmp; + } + + _csi_free (ctx, string->string); + _csi_slab_free (ctx, string, sizeof (csi_string_t)); + } else + ctx->free_string = string; +#endif +} + +csi_status_t +csi_object_execute (csi_t *ctx, csi_object_t *obj) +{ + csi_status_t status; + csi_object_t indirect; + + INDIRECT: + switch (obj->type & CSI_OBJECT_TYPE_MASK) { + case CSI_OBJECT_TYPE_NAME: + status = _csi_name_lookup (ctx, obj->datum.name, &indirect); + if (_csi_unlikely (status)) + return status; + if (indirect.type & CSI_OBJECT_ATTR_EXECUTABLE) { + obj = &indirect; + goto INDIRECT; + } else + return _csi_push_ostack_copy (ctx, &indirect); + + case CSI_OBJECT_TYPE_OPERATOR: + return obj->datum.op (ctx); + + case CSI_OBJECT_TYPE_ARRAY: + return _csi_array_execute (ctx, obj->datum.array); + case CSI_OBJECT_TYPE_FILE: + return _csi_file_execute (ctx, obj->datum.file); + case CSI_OBJECT_TYPE_STRING: + return _csi_string_execute (ctx, obj->datum.string); + + default: + return _csi_push_ostack_copy (ctx, obj); + } +} + +csi_object_t * +csi_object_reference (csi_object_t *obj) +{ + if (CSI_OBJECT_IS_CAIRO (obj)) { + switch (obj->type & CSI_OBJECT_TYPE_MASK) { + case CSI_OBJECT_TYPE_CONTEXT: + cairo_reference (obj->datum.cr); + break; + case CSI_OBJECT_TYPE_FONT: + cairo_font_face_reference (obj->datum.font_face); + break; + case CSI_OBJECT_TYPE_PATTERN: + cairo_pattern_reference (obj->datum.pattern); + break; + case CSI_OBJECT_TYPE_SCALED_FONT: + cairo_scaled_font_reference (obj->datum.scaled_font); + break; + case CSI_OBJECT_TYPE_SURFACE: + cairo_surface_reference (obj->datum.surface); + break; + } + } else if (CSI_OBJECT_IS_COMPOUND (obj)) { + obj->datum.object->ref++; + } + + return obj; +} + +void +csi_object_free (csi_t *ctx, + csi_object_t *obj) +{ + if (CSI_OBJECT_IS_CAIRO (obj)) { + switch (obj->type & CSI_OBJECT_TYPE_MASK) { + case CSI_OBJECT_TYPE_CONTEXT: + cairo_destroy (obj->datum.cr); + break; + case CSI_OBJECT_TYPE_FONT: + cairo_font_face_destroy (obj->datum.font_face); + break; + case CSI_OBJECT_TYPE_PATTERN: + cairo_pattern_destroy (obj->datum.pattern); + break; + case CSI_OBJECT_TYPE_SCALED_FONT: + cairo_scaled_font_destroy (obj->datum.scaled_font); + break; + case CSI_OBJECT_TYPE_SURFACE: + cairo_surface_destroy (obj->datum.surface); + break; + } + } else if (CSI_OBJECT_IS_COMPOUND (obj)) { + if (--obj->datum.object->ref) + return; + + switch (obj->type & CSI_OBJECT_TYPE_MASK) { + case CSI_OBJECT_TYPE_ARRAY: + csi_array_free (ctx, obj->datum.array); + break; + case CSI_OBJECT_TYPE_DICTIONARY: + csi_dictionary_free (ctx, obj->datum.dictionary); + break; + case CSI_OBJECT_TYPE_FILE: + _csi_file_free (ctx, obj->datum.file); + break; + case CSI_OBJECT_TYPE_MATRIX: + csi_matrix_free (ctx, obj->datum.matrix); + break; + case CSI_OBJECT_TYPE_STRING: + csi_string_free (ctx, obj->datum.string); + break; + default: + break; + } + } +} + +csi_status_t +csi_object_as_file (csi_t *ctx, + csi_object_t *src, + csi_object_t *file) +{ + int type = csi_object_get_type (src); + switch (type) { + case CSI_OBJECT_TYPE_FILE: + *file = *csi_object_reference (src); + return CSI_STATUS_SUCCESS; + case CSI_OBJECT_TYPE_STRING: + return csi_file_new_from_string (ctx, file, src->datum.string); + case CSI_OBJECT_TYPE_ARRAY: +#if 0 + if (src->type & CSI_OBJECT_ATTR_EXECUTABLE) + return _csi_file_new_from_procedure (cs, src); +#endif + default: + return _csi_error (CSI_STATUS_INVALID_SCRIPT); + } +} + +static int +lexcmp (void const *a, size_t alen, + void const *b, size_t blen) +{ + size_t len = alen < blen ? alen : blen; + int cmp = memcmp (a, b, len); + if (cmp) + return cmp; + if (alen == blen) + return 0; + return alen < blen ? -1 : +1; +} + +csi_boolean_t +csi_object_eq (csi_object_t *a, + csi_object_t *b) +{ + csi_object_type_t atype = csi_object_get_type (a); + csi_object_type_t btype = csi_object_get_type (b); + + if (atype == btype) { + switch (atype) { + case CSI_OBJECT_TYPE_BOOLEAN: + return a->datum.boolean == b->datum.boolean; + case CSI_OBJECT_TYPE_INTEGER: + return a->datum.integer == b->datum.integer; + case CSI_OBJECT_TYPE_REAL: + return a->datum.real == b->datum.real; + case CSI_OBJECT_TYPE_NAME: + return a->datum.name == b->datum.name; + case CSI_OBJECT_TYPE_STRING: + return 0 == lexcmp (a->datum.string->string, + a->datum.string->len, + b->datum.string->string, + b->datum.string->len); + case CSI_OBJECT_TYPE_NULL: + case CSI_OBJECT_TYPE_MARK: + return TRUE; + case CSI_OBJECT_TYPE_OPERATOR: + return a->datum.op == b->datum.op; + case CSI_OBJECT_TYPE_ARRAY: + case CSI_OBJECT_TYPE_DICTIONARY: + case CSI_OBJECT_TYPE_FILE: + case CSI_OBJECT_TYPE_MATRIX: + case CSI_OBJECT_TYPE_CONTEXT: + case CSI_OBJECT_TYPE_FONT: + case CSI_OBJECT_TYPE_PATTERN: + case CSI_OBJECT_TYPE_SCALED_FONT: + case CSI_OBJECT_TYPE_SURFACE: + return a->datum.ptr == b->datum.ptr; + } + } + + if (atype < btype) { + csi_object_t *c; + csi_object_type_t ctype; + c = a; a = b; b = c; + ctype = atype; atype = btype; btype = ctype; + } + + switch ((int) atype) { + case CSI_OBJECT_TYPE_INTEGER: + if (btype == CSI_OBJECT_TYPE_BOOLEAN) { + return a->datum.integer == b->datum.boolean; + } + break; + case CSI_OBJECT_TYPE_REAL: + if (btype == CSI_OBJECT_TYPE_INTEGER) { + return a->datum.real == b->datum.integer; + } + else if (btype == CSI_OBJECT_TYPE_BOOLEAN) { + return a->datum.real == b->datum.boolean; + } + break; + + case CSI_OBJECT_TYPE_STRING: + if (btype == CSI_OBJECT_TYPE_NAME) { + const char *bstr = (const char *) b->datum.name; + return 0 == lexcmp (a->datum.string->string, + a->datum.string->len, + bstr, + strlen (bstr)); + } + break; + + default: + break; + } + + return FALSE; +} + +csi_status_t +csi_object_compare (csi_object_t *a, + csi_object_t *b, + int *out) +{ + csi_object_type_t atype = csi_object_get_type (a); + csi_object_type_t btype = csi_object_get_type (b); + int sign; + + if (csi_object_eq (a, b)){ + *out = 0; + return CSI_STATUS_SUCCESS; + } + +#define CMP(x,y) ((x) < (y) ? -1 : +1) + + if (atype == btype) { + switch (atype) { + case CSI_OBJECT_TYPE_BOOLEAN: + *out = CMP (a->datum.boolean, b->datum.boolean); + return CSI_STATUS_SUCCESS; + case CSI_OBJECT_TYPE_INTEGER: + *out = CMP (a->datum.integer, b->datum.integer); + return CSI_STATUS_SUCCESS; + case CSI_OBJECT_TYPE_REAL: + *out = CMP (a->datum.real, b->datum.real); + return CSI_STATUS_SUCCESS; + case CSI_OBJECT_TYPE_NAME: { + const char *x = (char const *) a->datum.name; + const char *y = (char const *) b->datum.name; + *out = lexcmp (x, strlen(x), y, strlen (y)); + return CSI_STATUS_SUCCESS; + } + case CSI_OBJECT_TYPE_STRING: + *out = lexcmp (a->datum.string->string, + a->datum.string->len, + b->datum.string->string, + b->datum.string->len); + return CSI_STATUS_SUCCESS; + case CSI_OBJECT_TYPE_NULL: + case CSI_OBJECT_TYPE_MARK: + case CSI_OBJECT_TYPE_OPERATOR: + case CSI_OBJECT_TYPE_ARRAY: + case CSI_OBJECT_TYPE_DICTIONARY: + case CSI_OBJECT_TYPE_FILE: + case CSI_OBJECT_TYPE_MATRIX: + case CSI_OBJECT_TYPE_CONTEXT: + case CSI_OBJECT_TYPE_FONT: + case CSI_OBJECT_TYPE_PATTERN: + case CSI_OBJECT_TYPE_SCALED_FONT: + case CSI_OBJECT_TYPE_SURFACE: + goto TYPE_CHECK_ERROR; + } + } + + sign = +1; + if (atype < btype) { + csi_object_t *c; + csi_object_type_t ctype; + c = a; a = b; b = c; + ctype = atype; atype = btype; btype = ctype; + sign = -1; + } + + switch ((int) atype) { + case CSI_OBJECT_TYPE_INTEGER: + if (btype == CSI_OBJECT_TYPE_BOOLEAN) { + *out = sign * CMP (a->datum.integer, !!b->datum.boolean); + return CSI_STATUS_SUCCESS; + } + break; + case CSI_OBJECT_TYPE_REAL: + if (btype == CSI_OBJECT_TYPE_INTEGER) { + *out = sign * CMP (a->datum.real, b->datum.integer); + return CSI_STATUS_SUCCESS; + } + else if (btype == CSI_OBJECT_TYPE_BOOLEAN) { + *out = sign * CMP (a->datum.real, !!b->datum.boolean); + return CSI_STATUS_SUCCESS; + } + break; + + case CSI_OBJECT_TYPE_STRING: + if (btype == CSI_OBJECT_TYPE_NAME) { + const char *bstr = (const char *) b->datum.name; + *out = sign * lexcmp (a->datum.string->string, + a->datum.string->len, + bstr, + strlen (bstr)); + return CSI_STATUS_SUCCESS; + } + break; + + default: + break; + } + +#undef CMP + + TYPE_CHECK_ERROR: + return _csi_error (CSI_STATUS_SCRIPT_INVALID_TYPE); +} |