csi_status_t
csi_file_new_for_stream (csi_t *ctx,
	                 csi_object_t *obj,
			 FILE *stream)
{
    csi_file_t *file;

    file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
    if (file == NULL)
	return _csi_error (CAIRO_STATUS_NO_MEMORY);

    file->base.type = CSI_OBJECT_TYPE_FILE;
    file->base.ref = 1;

    file->data = NULL;
    file->type = STDIO;
    file->flags = 0;
    file->src = stream;
    if (file->src == NULL) {
	_csi_slab_free (ctx, file, sizeof (csi_file_t));
	return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
    }

    file->data = _csi_alloc (ctx, CHUNK_SIZE);
    if (file->data == NULL) {
	_csi_slab_free (ctx, file, sizeof (csi_file_t));
	return _csi_error (CAIRO_STATUS_NO_MEMORY);
    }
    file->bp = file->data;
    file->rem = 0;

    obj->type = CSI_OBJECT_TYPE_FILE;
    obj->datum.file = file;
    return CAIRO_STATUS_SUCCESS;
}
void *
_csi_perm_alloc (csi_t *ctx, int size)
{
    csi_chunk_t *chunk;
    void *ptr;

    size = (size + sizeof (void *)-1) & -sizeof (void *);

    chunk = ctx->perm_chunk;
    if (chunk == NULL || chunk->rem < size) {
	int chunk_size = (size + 8191) & -8192;
	chunk = _csi_alloc (ctx, sizeof (csi_chunk_t) + chunk_size);
	if (_csi_unlikely (chunk == NULL))
	    return NULL;

	chunk->rem = chunk_size;
	chunk->ptr = (char *) (chunk + 1);
	chunk->next = ctx->perm_chunk;
	ctx->perm_chunk = chunk;
    }

    ptr = chunk->ptr;
    chunk->ptr += size;
    chunk->rem -= size;

    return ptr;
}
csi_status_t
csi_file_new (csi_t *ctx,
	      csi_object_t *obj,
	      const char *path, const char *mode)
{
    csi_file_t *file;

    file = _csi_slab_alloc (ctx, sizeof (csi_file_t));
    if (file == NULL)
	return _csi_error (CAIRO_STATUS_NO_MEMORY);

    file->base.type = CSI_OBJECT_TYPE_FILE;
    file->base.ref = 1;

    file->data = NULL;
    file->type = STDIO;
    file->flags = OWN_STREAM;
    file->src = fopen (path, mode);
    if (file->src == NULL) {
	_csi_slab_free (ctx, file, sizeof (csi_file_t));
	return _csi_error (CAIRO_STATUS_FILE_NOT_FOUND);
    }

    file->data = _csi_alloc (ctx, CHUNK_SIZE);
    if (file->data == NULL) {
	_csi_slab_free (ctx, file, sizeof (csi_file_t));
	return _csi_error (CAIRO_STATUS_NO_MEMORY);
    }
    file->bp = file->data;
    file->rem = 0;

    obj->type = CSI_OBJECT_TYPE_FILE;
    obj->datum.file = file;
    return CAIRO_STATUS_SUCCESS;
}
void *
_csi_alloc0 (csi_t *ctx, int size)
{
    void *ptr;

    ptr = _csi_alloc (ctx, size);
    if (_csi_likely (ptr != NULL))
	memset (ptr, 0, size);

    return ptr;
}
Exemple #5
0
csi_status_t
_csi_stack_roll (csi_t *ctx,
		 csi_stack_t *stack,
		 csi_integer_t mod, csi_integer_t n)
{
    csi_object_t stack_copy[128];
    csi_object_t *copy;
    csi_integer_t last, i, len;

    switch (mod) { /* special cases */
    case 1:
	last = stack->len - 1;
	stack_copy[0] = stack->objects[last];
	for (i = last; --n; i--)
	    stack->objects[i] = stack->objects[i-1];
	stack->objects[i] = stack_copy[0];
	return CSI_STATUS_SUCCESS;
    case -1:
	last = stack->len - 1;
	stack_copy[0] = stack->objects[i = last - n + 1];
	for (; --n; i++)
	    stack->objects[i] = stack->objects[i+1];
	stack->objects[i] = stack_copy[0];
	return CSI_STATUS_SUCCESS;
    }

    /* fall back to a copy */
    if (n > ARRAY_LENGTH (stack_copy)) {
	if (_csi_unlikely ((unsigned) n > INT_MAX / sizeof (csi_object_t)))
	    return _csi_error (CSI_STATUS_NO_MEMORY);
	copy = _csi_alloc (ctx, n * sizeof (csi_object_t));
	if (copy == NULL)
	    return _csi_error (CSI_STATUS_NO_MEMORY);
    } else
	copy = stack_copy;

    i = stack->len - n;
    memcpy (copy, stack->objects + i, n * sizeof (csi_object_t));
    mod = -mod;
    if (mod < 0)
	mod += n;
    last = mod;
    for (len = n; n--; i++) {
	stack->objects[i] = copy[last];
	if (++last == len)
	    last = 0;
    }

    if (copy != stack_copy)
	_csi_free (ctx, copy);

    return CSI_STATUS_SUCCESS;
}
Exemple #6
0
csi_status_t
_csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size)
{
    csi_status_t status = CSI_STATUS_SUCCESS;

    stack->len = 0;
    stack->size = size;
    /* assert ((unsigned) size < INT_MAX / sizeof (csi_object_t)); */
    stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t));
    if (_csi_unlikely (stack->objects == NULL))
	status = _csi_error (CSI_STATUS_NO_MEMORY);

    return status;
}
void *
_csi_slab_alloc (csi_t *ctx, int size)
{
#if CSI_DEBUG_MALLOC
    return malloc (size);
#else
    int chunk_size;
    csi_chunk_t *chunk;
    void *ptr;

    chunk_size = 2 * sizeof (void *);
    chunk_size = (size + chunk_size - 1) / chunk_size;

    if (ctx->slabs[chunk_size].free_list) {
	ptr = ctx->slabs[chunk_size].free_list;
	ctx->slabs[chunk_size].free_list = *(void **) ptr;
	return ptr;
    }

    chunk = ctx->slabs[chunk_size].chunk;
    if (chunk == NULL || ! chunk->rem) {
	int cnt = MAX (128, 8192 / (chunk_size * 2 * sizeof (void *)));

	chunk = _csi_alloc (ctx,
			    sizeof (csi_chunk_t) +
			    cnt * chunk_size * 2 * sizeof (void *));
	if (_csi_unlikely (chunk == NULL))
	    return NULL;

	chunk->rem = cnt;
	chunk->ptr = (char *) (chunk + 1);
	chunk->next = ctx->slabs[chunk_size].chunk;
	ctx->slabs[chunk_size].chunk = chunk;
    }

    ptr = chunk->ptr;
    chunk->ptr += chunk_size * 2 * sizeof (void *);
    chunk->rem--;

    return ptr;
#endif
}
csi_status_t
csi_file_new_from_stream (csi_t *ctx,
			  FILE *file,
			  csi_object_t **out)
{
    csi_file_t *obj;

    obj = (csi_file_t *) _csi_object_new (ctx, CSI_OBJECT_TYPE_FILE);
    if (obj == NULL)
	return _csi_error (CAIRO_STATUS_NO_MEMORY);

    obj->type = STDIO;
    obj->src = file;
    obj->data = _csi_alloc (ctx, CHUNK_SIZE);
    if (obj->data == NULL) {
	csi_object_free (&obj->base);
	return _csi_error (CAIRO_STATUS_UNDEFINED_FILENAME_ERROR);
    }
    obj->bp = obj->data;
    obj->rem = 0;

    *out = &obj->base;
    return CAIRO_STATUS_SUCCESS;
}