diff options
Diffstat (limited to 'fitz/obj_array.c')
-rw-r--r-- | fitz/obj_array.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/fitz/obj_array.c b/fitz/obj_array.c new file mode 100644 index 00000000..3953470a --- /dev/null +++ b/fitz/obj_array.c @@ -0,0 +1,230 @@ +#include "fitz-base.h" +#include "fitz-stream.h" + +void fz_droparray(fz_obj *obj); + +fz_error * +fz_newarray(fz_obj **op, int initialcap) +{ + fz_obj *obj; + int i; + + obj = *op = fz_malloc(sizeof (fz_obj)); + if (!obj) + return fz_throw("outofmem: array struct"); + + obj->refs = 1; + obj->kind = FZ_ARRAY; + + obj->u.a.len = 0; + obj->u.a.cap = initialcap > 0 ? initialcap : 6; + + obj->u.a.items = fz_malloc(sizeof (fz_obj*) * obj->u.a.cap); + if (!obj->u.a.items) + { + fz_free(obj); + return fz_throw("outofmem: array item buffer"); + } + + for (i = 0; i < obj->u.a.cap; i++) + obj->u.a.items[i] = nil; + + return fz_okay; +} + +fz_error * +fz_copyarray(fz_obj **op, fz_obj *obj) +{ + fz_error *error; + fz_obj *new; + int i; + + if (!fz_isarray(obj)) + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); + + error = fz_newarray(&new, fz_arraylen(obj)); + if (error) + return fz_rethrow(error, "cannot create new array"); + + for (i = 0; i < fz_arraylen(obj); i++) + { + error = fz_arraypush(new, fz_arrayget(obj, i)); + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot add item to array"); + } + } + + *op = new; + + return fz_okay; +} + +fz_error * +fz_deepcopyarray(fz_obj **op, fz_obj *obj) +{ + fz_error *error; + fz_obj *new; + fz_obj *val; + int i; + + if (!fz_isarray(obj)) + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); + + error = fz_newarray(&new, fz_arraylen(obj)); + if (error) + return fz_rethrow(error, "cannot create new array"); + + for (i = 0; i < fz_arraylen(obj); i++) + { + val = fz_arrayget(obj, i); + + if (fz_isarray(val)) + { + error = fz_deepcopyarray(&val, val); + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot deep copy item"); + } + + error = fz_arraypush(new, val); + if (error) + { + fz_dropobj(val); + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } + + fz_dropobj(val); + } + + else if (fz_isdict(val)) + { + error = fz_deepcopydict(&val, val); + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot deep copy item"); + } + + error = fz_arraypush(new, val); + if (error) + { + fz_dropobj(val); + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } + fz_dropobj(val); + } + + else + { + error = fz_arraypush(new, val); + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } + } + } + + *op = new; + + return fz_okay; +} + +int +fz_arraylen(fz_obj *obj) +{ + if (!fz_isarray(obj)) + return 0; + return obj->u.a.len; +} + +fz_obj * +fz_arrayget(fz_obj *obj, int i) +{ + if (!fz_isarray(obj)) + return nil; + + if (i < 0 || i >= obj->u.a.len) + return nil; + + return obj->u.a.items[i]; +} + +fz_error * +fz_arrayput(fz_obj *obj, int i, fz_obj *item) +{ + if (!fz_isarray(obj)) + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); + if (i < 0) + return fz_throw("assert: index %d < 0", i); + if (i >= obj->u.a.len) + return fz_throw("assert: index %d > length %d", i, obj->u.a.len); + + if (obj->u.a.items[i]) + fz_dropobj(obj->u.a.items[i]); + obj->u.a.items[i] = fz_keepobj(item); + + return fz_okay; +} + +static fz_error * +growarray(fz_obj *obj) +{ + fz_obj **newitems; + int newcap; + int i; + + newcap = obj->u.a.cap * 2; + newitems = fz_realloc(obj->u.a.items, sizeof (fz_obj*) * newcap); + if (!newitems) + return fz_throw("outofmem: resize item buffer"); + + obj->u.a.items = newitems; + for (i = obj->u.a.cap ; i < newcap; i++) + obj->u.a.items[i] = nil; + obj->u.a.cap = newcap; + + return fz_okay; +} + +fz_error * +fz_arraypush(fz_obj *obj, fz_obj *item) +{ + fz_error *error; + + if (!fz_isarray(obj)) + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); + + if (obj->u.a.len + 1 > obj->u.a.cap) + { + error = growarray(obj); + if (error) + return fz_rethrow(error, "cannot grow item buffer"); + } + + obj->u.a.items[obj->u.a.len] = fz_keepobj(item); + obj->u.a.len++; + + return fz_okay; +} + +void +fz_droparray(fz_obj *obj) +{ + int i; + + assert(obj->kind == FZ_ARRAY); + + for (i = 0; i < obj->u.a.len; i++) + if (obj->u.a.items[i]) + fz_dropobj(obj->u.a.items[i]); + + fz_free(obj->u.a.items); + fz_free(obj); +} + |