diff --git a/util/cairo-script/cairo-script-objects.c b/util/cairo-script/cairo-script-objects.c index f4726cefb..bf00b15df 100644 --- a/util/cairo-script/cairo-script-objects.c +++ b/util/cairo-script/cairo-script-objects.c @@ -664,3 +664,95 @@ csi_object_as_file (csi_t *ctx, 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; +} diff --git a/util/cairo-script/cairo-script-operators.c b/util/cairo-script/cairo-script-operators.c index cde54c2a9..13bfc82f0 100644 --- a/util/cairo-script/cairo-script-operators.c +++ b/util/cairo-script/cairo-script-operators.c @@ -1210,69 +1210,7 @@ _eq (csi_t *ctx) b = _csi_peek_ostack (ctx, 0); a = _csi_peek_ostack (ctx, 1); - if (csi_object_get_type (a) != csi_object_get_type (b)) { - switch ((int) csi_object_get_type (a)) { - case CSI_OBJECT_TYPE_BOOLEAN: - switch ((int) csi_object_get_type (b)) { - case CSI_OBJECT_TYPE_INTEGER: - v = a->datum.boolean == !! b->datum.integer; - break; - case CSI_OBJECT_TYPE_REAL: - v = a->datum.boolean == (b->datum.real != 0); - break; - default: - return _csi_error (CSI_STATUS_INVALID_SCRIPT); - } - break; - - case CSI_OBJECT_TYPE_INTEGER: - switch ((int) csi_object_get_type (b)) { - case CSI_OBJECT_TYPE_BOOLEAN: - v = a->datum.integer == b->datum.boolean; - break; - case CSI_OBJECT_TYPE_REAL: - v = a->datum.integer == b->datum.real; - break; - default: - return _csi_error (CSI_STATUS_INVALID_SCRIPT); - } - break; - - case CSI_OBJECT_TYPE_REAL: - switch ((int) csi_object_get_type (b)) { - case CSI_OBJECT_TYPE_BOOLEAN: - v = a->datum.real == b->datum.boolean; - break; - case CSI_OBJECT_TYPE_INTEGER: - v = a->datum.real == b->datum.integer; - break; - default: - return _csi_error (CSI_STATUS_INVALID_SCRIPT); - } - break; - - default: - return _csi_error (CSI_STATUS_INVALID_SCRIPT); - } - } else { - if (CSI_OBJECT_IS_CAIRO (a)) { - v = a->datum.ptr == b->datum.ptr; - } else if (CSI_OBJECT_IS_COMPOUND (a)) { - v = a->datum.object == b->datum.object; - } else switch ((int) csi_object_get_type (a)) { - case CSI_OBJECT_TYPE_BOOLEAN: - v = a->datum.boolean == b->datum.boolean; - break; - case CSI_OBJECT_TYPE_INTEGER: - v = a->datum.integer == b->datum.integer; - break; - case CSI_OBJECT_TYPE_REAL: - v = a->datum.real == b->datum.real; - break; - default: - return _csi_error (CSI_STATUS_INVALID_SCRIPT); - } - } + v = csi_object_eq (a, b); pop (2); return _csi_push_ostack_boolean (ctx, v); diff --git a/util/cairo-script/cairo-script-private.h b/util/cairo-script/cairo-script-private.h index 8ab1f63a6..819f25c3f 100644 --- a/util/cairo-script/cairo-script-private.h +++ b/util/cairo-script/cairo-script-private.h @@ -716,6 +716,10 @@ csi_object_as_file (csi_t *ctx, csi_object_t *src, csi_object_t *file); +csi_private csi_boolean_t +csi_object_eq (csi_object_t *a, + csi_object_t *b); + /* cairo-script-operators.c */ csi_private const csi_operator_def_t *