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; }
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; }
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; }