import { Address } from "./address"; class LocationHolder { public data: Address[]; private address_id: number constructor () { this.data = []; this.address_id = 0; } /** * * @param {*} value the value to be allocated * @returns {Number} - the address id */ allocate (value:any) : number { const id = this.address_id; const address = new Address(id, value); this.data.push(address); this.address_id += 1; return id; } /** * * @param {Number} id */ deallocate (id: number) : boolean { const index = this.findIndex(id); // console.log("Deallocation address "+ id); if(index !== -1) { this.data.splice(index, 1); return true; } return false; } /** * * @param {Number} id * @returns {Address} the address identified by id */ find (id: number): Address | null { let beg = 0 let end = this.data.length; // console.log("Finding address "+id); while (beg < end) { const med = Math.floor((beg + end)/2); const address = this.getAddressAt(med); if(address.id === id) { return address; } else if (id > address.id) { beg = med; } else { end = med } } return null; } getAddressAt (pos: number): Address { return this.data[pos]; } /** * * @param {Number} id address id * @returns {Number} the index of the address identified by id */ findIndex (id: number) : number { let beg = 0 let end = this.data.length; while (beg < end) { const med = Math.floor((beg + end)/2); const address = this.getAddressAt(med); if(address.id === id) { return med; } else if (id > address.id) { beg = med; } else { end = med } } return -1; } updateAddress (id: number, value: any, is_var = false): void { const index = this.findIndex(id); if(index === -1) { throw new Error("Invalid address..." + id); } this.data[index].value = value; this.data[index].is_var = is_var; } clear () { for (let i = 0; i < this.data.length; i += 1) { delete this.data[i]; } this.data = []; this.address_id = 0; } gc (): number { const to_remove = []; for (let i = 0; i < this.data.length; i += 1) { const address = this.data[i]; if (!address.is_var) { to_remove.push(address.id); } } to_remove.forEach(x => this.deallocate(x), this); return to_remove.length; } } const inner_ref = new LocationHolder(); export const Location = Object.freeze({ allocate: inner_ref.allocate.bind(inner_ref), deallocate: inner_ref.deallocate.bind(inner_ref), find: inner_ref.find.bind(inner_ref), updateAddress: inner_ref.updateAddress.bind(inner_ref), clear: inner_ref.clear.bind(inner_ref), gc: inner_ref.gc.bind(inner_ref), size: () => inner_ref.data.length });