
use mem

struct Bump {
    data: ptr
    size: uint
    index: uint (0)

    static fn new(size: uint (1000)) Bump {
        return Bump {
            size: size
            data: mem:alloc(size)
        }
    }

    fn get(isize: uint) ptr {
        let i = this.index
        let size = this.size
        let new_index = i + isize

        if new_index > size {
            let new_size = size * 2
            while new_index > new_size : new_size *= 2
            this.data = mem:resize(this.data, size, new_size)
            this.size = new_size
        }

        this.index = new_index
        return this.data + i
    }

    fn minimum_size(size: uint) {
        if size > this.size {
            this.data = mem:resize(this.data, this.size, size)
            this.size = size
        }
    }

    fn reset() {
        this.index = 0
    }

    fn free() {
        mem:free(this.data)
        mem:free(this)
    }

    fn add_ptr(item: ptr) {
        let adr = this.get(size_of(ptr))
        @ptrv(adr, ptr) = item
    }

    fn reduce_size() {
        let index = this.index
        let index2 = index * 2
        if index2 < 1024 : index2 = 1024
        if index2 < this.size {
            this.data = mem:resize(this.data, this.index, index2)
            this.size = index2
        }
    }

    fn loop_items[T](func: fn(T)(), reset: bool) {

        let data = this.data
        let adr = data
        let end = adr + this.index
        if reset : this.reset()

        while adr < end {
            let item = @ptrv(adr, T)
            func(item)
            adr += size_of(T)
        }
    }
}
