mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 21:00:10 +01:00
667 lines
16 KiB
C
667 lines
16 KiB
C
|
|
/*
|
||
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "cairo-script-private.h"
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
csi_status_t
|
||
|
|
csi_array_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj)
|
||
|
|
|
||
|
|
{
|
||
|
|
csi_array_t *array;
|
||
|
|
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);
|
||
|
|
|
||
|
|
array->base.type = CSI_OBJECT_TYPE_ARRAY;
|
||
|
|
array->base.ref = 1;
|
||
|
|
status = _csi_stack_init (ctx, &array->stack, 32);
|
||
|
|
if (_csi_unlikely (status)) {
|
||
|
|
_csi_slab_free (ctx, array, sizeof (csi_array_t));
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
_csi_stack_fini (ctx, &array->stack);
|
||
|
|
_csi_slab_free (ctx, array, sizeof (csi_array_t));
|
||
|
|
}
|
||
|
|
|
||
|
|
csi_status_t
|
||
|
|
csi_boolean_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj,
|
||
|
|
csi_boolean_t v)
|
||
|
|
{
|
||
|
|
obj->type = CSI_OBJECT_TYPE_BOOLEAN;
|
||
|
|
obj->datum.boolean = v;
|
||
|
|
|
||
|
|
return CSI_STATUS_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static cairo_bool_t
|
||
|
|
_dictionary_name_equal (const void *_a, const void *_b)
|
||
|
|
{
|
||
|
|
const csi_dictionary_entry_t *a = _a;
|
||
|
|
const csi_dictionary_entry_t *b = _b;
|
||
|
|
return a->hash_entry.hash == b->hash_entry.hash;
|
||
|
|
}
|
||
|
|
|
||
|
|
csi_status_t
|
||
|
|
csi_dictionary_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj)
|
||
|
|
|
||
|
|
{
|
||
|
|
csi_dictionary_t *dict;
|
||
|
|
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);
|
||
|
|
|
||
|
|
dict->base.type = CSI_OBJECT_TYPE_DICTIONARY;
|
||
|
|
dict->base.ref = 1;
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
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);
|
||
|
|
_csi_hash_table_fini (&dict->hash_table);
|
||
|
|
|
||
|
|
_csi_slab_free (ctx, dict, sizeof (csi_dictionary_t));
|
||
|
|
}
|
||
|
|
|
||
|
|
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_integer_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj,
|
||
|
|
csi_integer_t v)
|
||
|
|
{
|
||
|
|
obj->type = CSI_OBJECT_TYPE_INTEGER;
|
||
|
|
obj->datum.integer = v;
|
||
|
|
|
||
|
|
return CSI_STATUS_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
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, -1);
|
||
|
|
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_operator_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj,
|
||
|
|
csi_operator_t op)
|
||
|
|
{
|
||
|
|
obj->type = CSI_OBJECT_TYPE_OPERATOR | CSI_OBJECT_ATTR_EXECUTABLE;
|
||
|
|
obj->datum.op = op;
|
||
|
|
|
||
|
|
return CSI_STATUS_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
csi_status_t
|
||
|
|
csi_real_new (csi_t *ctx,
|
||
|
|
csi_object_t *obj,
|
||
|
|
csi_real_t v)
|
||
|
|
{
|
||
|
|
obj->type = CSI_OBJECT_TYPE_REAL;
|
||
|
|
obj->datum.real = v;
|
||
|
|
|
||
|
|
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;
|
||
|
|
|
||
|
|
string = _csi_slab_alloc (ctx, sizeof (csi_string_t));
|
||
|
|
if (_csi_unlikely (string == NULL))
|
||
|
|
return _csi_error (CSI_STATUS_NO_MEMORY);
|
||
|
|
|
||
|
|
string->base.type = CSI_OBJECT_TYPE_STRING;
|
||
|
|
string->base.ref = 1;
|
||
|
|
|
||
|
|
if (len < 0)
|
||
|
|
len = strlen (str);
|
||
|
|
if (_csi_unlikely (len >= INT32_MAX)) {
|
||
|
|
_csi_slab_free (ctx, string, sizeof (csi_string_t));
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
memcpy (string->string, str, len);
|
||
|
|
string->string[len] = '\0';
|
||
|
|
string->len = len;
|
||
|
|
|
||
|
|
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, &ctx->scanner, obj.datum.file);
|
||
|
|
csi_object_free (ctx, &obj);
|
||
|
|
|
||
|
|
return status;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
csi_string_free (csi_t *ctx, csi_string_t *string)
|
||
|
|
{
|
||
|
|
_csi_free (ctx, string->string);
|
||
|
|
_csi_slab_free (ctx, string, sizeof (csi_string_t));
|
||
|
|
}
|
||
|
|
|
||
|
|
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)
|
||
|
|
{
|
||
|
|
|
||
|
|
switch ((int) csi_object_get_type (src)) {
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
}
|