| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938 |
- /*
- * 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);
- }
|