#include 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_outofmem; obj->kind = FZ_ARRAY; obj->refcount = 1; 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_outofmem; } for (i = 0; i < obj->u.a.cap; i++) obj->u.a.items[i] = nil; return nil; } fz_error * fz_copyarray(fz_obj **op, fz_obj *obj) { fz_error *err; fz_obj *new; int i; if (!fz_isarray(obj)) return fz_throw("typecheck in copyarray"); err = fz_newarray(&new, fz_arraylen(obj)); if (err) return err; *op = new; for (i = 0; i < fz_arraylen(obj); i++) { err = fz_arraypush(new, fz_arrayget(obj, i)); if (err) { fz_droparray(new); return err; } } return nil; } fz_error * fz_deepcopyarray(fz_obj **op, fz_obj *obj) { fz_error *err; fz_obj *new; fz_obj *val; int i; if (!fz_isarray(obj)) return fz_throw("typecheck in deepcopyarray"); err = fz_newarray(&new, fz_arraylen(obj)); if (err) return err; *op = new; for (i = 0; i < fz_arraylen(obj); i++) { val = fz_arrayget(obj, i); if (fz_isarray(val)) { err = fz_deepcopyarray(&val, val); if (err) { fz_droparray(new); return err; } err = fz_arraypush(new, val); if (err) { fz_dropobj(val); fz_droparray(new); return err; } fz_dropobj(val); } else if (fz_isdict(val)) { err = fz_deepcopydict(&val, val); if (err) { fz_droparray(new); return err; } err = fz_arraypush(new, val); if (err) { fz_dropobj(val); fz_droparray(new); return err; } fz_dropobj(val); } else { err = fz_arraypush(new, val); if (err) { fz_droparray(new); return err; } } } return nil; } 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("typecheck in arrayput"); if (i < 0) return fz_throw("rangecheck in arrayput: %d < 0", i); if (i >= obj->u.a.len) return fz_throw("rangecheck in arrayput: %d > %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 nil; } 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_outofmem; 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 nil; } fz_error * fz_arraypush(fz_obj *obj, fz_obj *item) { fz_error *err; if (!fz_isarray(obj)) return fz_throw("typecheck in arraypush"); if (obj->u.a.len + 1 > obj->u.a.cap) { err = growarray(obj); if (err) return err; } obj->u.a.items[obj->u.a.len] = fz_keepobj(item); obj->u.a.len++; return nil; } 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); }