//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 26 Dec 05 Brian Frank Creation
// 19 Aug 06 Brian Frank Ported from Java to Fan
//
**
** FTable is a 16-bit indexed lookup table for pod constants.
**
class FTable
{
//////////////////////////////////////////////////////////////////////////
// Factories
//////////////////////////////////////////////////////////////////////////
static FTable makeStrs(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { out.writeUtf((Str)obj) },
|InStream in->Obj| { in.readUtf.intern })
}
static FTable makeTypeRefs(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { ((FTypeRef)obj).write(out) },
|InStream in->Obj| { FTypeRef.read(in) })
}
static FTable makeFieldRefs(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { ((FFieldRef)obj).write(out) },
|InStream in->Obj| { FFieldRef.read(in) })
}
static FTable makeMethodRefs(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { ((FMethodRef)obj).write(out) },
|InStream in->Obj| { FMethodRef.read(in) })
}
static FTable makeInts(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { out.writeI8((Int)obj) },
|InStream in->Obj| { in.readS8 })
}
static FTable makeFloats(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { out.writeF8((Float)obj) },
|InStream in->Obj| { in.readF8 })
}
static FTable makeDecimals(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { out.writeDecimal((Decimal)obj) },
|InStream in->Obj| { in.readDecimal })
}
static FTable makeDurations(FPod pod)
{
return make(pod,
|OutStream out, Obj obj| { out.writeI8(((Duration)obj).ticks) },
|InStream in->Obj| { Duration(in.readS8) })
}
//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////
new make(FPod pod, |OutStream out, Obj obj| writer, |InStream in->Obj| reader)
{
this.pod = pod
this.writer = writer
this.reader = reader
this.table = [,]
this.reverse = Obj:Int[:]
}
//////////////////////////////////////////////////////////////////////////
// Access
//////////////////////////////////////////////////////////////////////////
**
** Return if this table is empty
**
Bool isEmpty()
{
return table.isEmpty
}
**
** Get the object identified by the specified 16-bit index.
**
@Operator Obj get(Int index)
{
return table[index]
}
**
** Perform a reverse lookup to map a value to it's index (only
** available at compile time). If the value isn't in the table
** yet, then add it.
**
Int add(Obj val)
{
index := reverse[val]
if (index == null)
{
index = table.size
table.add(val)
reverse[val] = index
}
return index
}
**
** Serialize.
**
FTable read(InStream? in)
{
table = [,]
if (in == null) return this
in.readU2.times { table.add(reader.call(in)) }
in.close
return this
}
**
** Deserialize.
**
Void write(OutStream out)
{
out.writeI2(table.size)
table.each |Obj obj| { writer.call(out, obj) }
out.close
}
//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////
FPod pod
Obj[] table
Obj:Int reverse
|OutStream out, Obj obj| writer
|InStream in->Obj| reader
}