DIRECTORY
CD, CDAtomicObjects, CDCells, CDRects, CDTexts, CDSymbolicObjects, CMosB, CMosBWellDifImpl, Convert, Core, CoreIO, CoreProperties, CoreGeometry, GList, HashTable, Rope;
CoreGeometryIOImpl:
CEDAR
PROGRAM
IMPORTS CD, CDAtomicObjects, CDCells, CDRects, CDSymbolicObjects, CDTexts, CMosB, CMosBWellDifImpl, Convert, CoreIO, CoreProperties, GList, HashTable, Rope
SHARES CDCells, CDRects, CDTexts, CDSymbolicObjects, CoreGeometry, CMosBWellDifImpl =
BEGIN OPEN CoreIO;
Object Class Registration
objectClassRegistry: HashTable.Table ← HashTable.Create[];
ObjectClassData: TYPE = REF ObjectClassDataRec;
ObjectClassDataRec:
TYPE =
RECORD [
write: ObjectClassWriteProc ← NIL,
read: ObjectClassReadProc ← NIL];
ObjectClassWriteProc:
TYPE =
PROC [h: Handle, me:
CD.Object];
ObjectClassReadProc:
TYPE =
PROC [h: Handle]
RETURNS [obj:
CD.Object];
RegisterObjectClass:
PROC [objectClass: CD.ObjectClass, write: ObjectClassWriteProc, read: ObjectClassReadProc] = {
data: ObjectClassData ← NEW[ObjectClassDataRec ← [write, read]];
IF write=NIL OR read=NIL THEN ERROR; -- if only one NIL then invariant for object write/read is broken
[] ← HashTable.Store[objectClassRegistry, objectClass.objectType, data];
};
Object Class IO Utilities
WriteInstance:
PROC [h: Handle, instance:
CD.Instance] = {
WriteObject[h, instance.ob];
WritePosition[h, instance.location];
WriteInt[h, instance.orientation];
WriteCDProperties[h, instance.properties];
};
ReadInstance:
PROC [h: Handle]
RETURNS [instance:
CD.Instance] = {
instance ← NEW [CD.InstanceRep ← [ob: NIL]];
instance.ob ← ReadObject[h];
instance.location ← ReadPosition[h];
instance.orientation ← ReadInt[h];
instance.properties ← ReadCDProperties[h];
};
WriteInstanceList:
PROC [h: Handle, instances:
LIST
OF
CD.Instance] = {
WriteInt[h, GList.Length[instances]];
WHILE instances#
NIL
DO
WriteInstance[h, instances.first];
instances ← instances.rest;
ENDLOOP;
};
ReadInstanceList:
PROC [h: Handle]
RETURNS [instances:
LIST
OF
CD.Instance ←
NIL] = {
THROUGH [1 .. ReadInt[h]]
DO
instances ← CONS [ReadInstance[h], instances];
ENDLOOP;
};
objectsAtom:
ATOM = RegisterProperty[$CoreGeometryIOObjects, WriteObjectsProp, ReadObjectsProp];
The prop write and read procedures are only called when the hash tables are initialized for reading, never for writing.
WriteObjectsProp: PropWriteProc = {
WriteHashTable[h, NARROW[value], WriteObjectIDPair];
};
WriteObjectIDPair: HashWriteProc = {
id: ROPE ← NARROW[key];
object: CD.Object ← NARROW[value];
WriteID[h, id];
WriteObject[h, object];
};
ReadObjectsProp: PropReadProc = {
value ← ReadHashTable[h, ReadObjectIDPair, HashTable.RopeEqual, HashTable.HashRope];
};
ReadObjectIDPair: HashReadProc = {
key ← ReadID[h];
value ← ReadObject[h];
};
A HashTable [CD.Object -> Rope ID] is stored on the handle under the key objectsAtom
CMosBObsImpl $C2DifShortCon, $C2LargeSimpleCon, $C2LargeVia, $C2LargeWellSimpleCon, $C2LTrans, $C2LWellTrans, $C2SimpleCon, $C2Trans, $C2Via, $C2WellDifShortCon, $C2WellSimpleCon, $C2WellTrans, $CLWellTrans
WriteObject:
PROC [h: Handle, obj:
CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPE ← NIL;
IF objects=
NIL
THEN {
objects ← HashTable.Create[];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← NARROW [HashTable.Fetch[objects, obj].value];
IF objectID=
NIL
THEN {
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, obj.class.objectType].value];
objectID ← Rope.Cat["O", Convert.RopeFromInt[from: HashTable.GetSize[objects], base: 16, showRadix: FALSE]];
IF NOT HashTable.Insert[objects, obj, objectID] THEN ERROR;
WriteID[h, objectID];
WriteAtom[h, obj.class.objectType];
IF classData=
NIL
THEN {
IF CDAtomicObjects.IsAtomicOb[obj]
THEN {
WritePosition[h, CD.InterestSize[obj]];
WriteLayer[h, obj.layer];
}
ELSE ERROR; -- no write proc and not atomic
}
ELSE classData.write[h, obj];
WriteCDProperties[h, obj.properties];
}
ELSE WriteID[h, objectID];
};
A HashTable [Rope ID -> CD.Object] is stored on the handle under the key objectsAtom
ReadObject:
PROC [h: Handle]
RETURNS [obj:
CD.Object] = {
objects: HashTable.Table ← NARROW [CoreProperties.GetProp[h.properties, objectsAtom]];
objectID: ROPE;
IF objects=
NIL
THEN {
objects ← HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
h.properties ← CoreProperties.PutProp[h.properties, objectsAtom, objects];
};
objectID ← ReadID[h];
IF Rope.Fetch[objectID]#'O THEN ERROR;
obj ← NARROW [HashTable.Fetch[objects, objectID].value];
IF obj=
NIL
THEN {
classAtom: ATOM ← ReadAtom[h];
classData: ObjectClassData ← NARROW[HashTable.Fetch[objectClassRegistry, classAtom].value];
IF classData=
NIL
THEN {
pos: CD.Position ← ReadPosition[h];
layer: CD.Layer ← ReadLayer[h];
obj ← CDAtomicObjects.CreateAtomicOb[classAtom, pos, CMosB.cmosB, layer];
}
ELSE obj ← classData.read[h];
obj.properties ← ReadCDProperties[h];
IF NOT HashTable.Insert[objects, objectID, obj] THEN ERROR;
};
};
WritePosition:
PROC [h: Handle, position:
CD.Position] = {
WriteInt[h, position.x];
WriteInt[h, position.y];
};
ReadPosition:
PROC [h: Handle]
RETURNS [position:
CD.Position] = {
position.x ← ReadInt[h];
position.y ← ReadInt[h];
};
WriteLayer:
PROC [h: Handle, layer:
CD.Layer] = {
WriteInt[h, layer];
};
ReadLayer:
PROC [h: Handle]
RETURNS [layer:
CD.Layer] = {
layer ← ReadInt[h];
};
WriteCDProperties:
PROC [h: Handle, properties:
CD.PropList] = {
props: Core.Properties ← NIL;
WHILE properties#
NIL
DO
IF ISTYPE [properties.first.key, ATOM] THEN props ← CoreProperties.PutProp[props, NARROW [properties.first.key], properties.first.val];
properties ← properties.rest;
ENDLOOP;
WriteProperties[h, props];
};
ReadCDProperties:
PROC [h: Handle]
RETURNS [properties:
CD.PropList ←
NIL] = {
Consume:
PROC [key:
ATOM, val:
REF] = {
properties ← CONS [[key, val], properties];
};
CoreProperties.Enumerate[ReadProperties[h], Consume];
};
WriteRect:
PROC [h: Handle, rect:
CD.Rect] = {
WriteInt[h, rect.x1]; WriteInt[h, rect.y1];
WriteInt[h, rect.x2]; WriteInt[h, rect.y2];
};
ReadRect:
PROC [h: Handle]
RETURNS [rect:
CD.Rect] = {
rect.x1 ← ReadInt[h]; rect.y1 ← ReadInt[h];
rect.x2 ← ReadInt[h]; rect.y2 ← ReadInt[h];
};
CoreIO Object Property IO
RectPropWrite: PropWriteProc = {WriteRect[h, NARROW [value, REF CD.Rect]^]};
RectPropRead: PropReadProc = {value ← NEW [CD.Rect ← ReadRect[h]]};
PinsPropWrite: PropWriteProc = {
WITH value SELECT FROM
instance: CD.Instance => {WriteInt[h, 1]; WriteInstance[h, instance]};
instances: CoreGeometryImpl.InstanceSeq => {
WriteInt[h, instances.size];
FOR i: NAT IN [0 .. instances.size) DO WriteInstance[h, instances[i]] ENDLOOP;
};
ENDCASE => ERROR; -- hack!
};
PinsPropRead: PropReadProc = {
size: NAT ← ReadInt[h];
instances: CoreGeometryImpl.InstanceSeq ← NEW [CoreGeometryImpl.InstanceSeqRec[size]];
FOR i: NAT IN [0 .. size) DO instances[i] ← ReadInstance[h] ENDLOOP;
value ← instances;
GeometryPropWrite: PropWriteProc = {
WriteInstanceList[h, NARROW [value]];
};
GeometryPropRead: PropReadProc = {value ← ReadInstanceList[h]};
InstancePropWrite: PropWriteProc = {WriteInstance[h,
NARROW [value]]};
InstancePropRead: PropReadProc = {value ← ReadInstance[h]};
Initialization
Register:
PROC [decoration: CoreGeometry.Decoration] = {
[] ← RegisterProperty[decoration.irProp, RectPropWrite, RectPropRead];
[] ← RegisterProperty[decoration.pinsProp, PinsPropWrite, PinsPropRead];
[] ← RegisterProperty[decoration.geometryProp, GeometryPropWrite, GeometryPropRead];
[] ← RegisterProperty[decoration.transfProp, InstancePropWrite, InstancePropRead];
};
RegisterObjectClass[CDRects.bareRectClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CDCells.cellClass, WriteCell, ReadCell];
RegisterObjectClass[CDSymbolicObjects.markClass, WriteMark, ReadMark];
RegisterObjectClass[CDSymbolicObjects.pinClass, WritePinOrSegment, ReadPin];
RegisterObjectClass[CDSymbolicObjects.segmentClass, WritePinOrSegment, ReadSegment];
RegisterObjectClass[CMosBWellDifImpl.wndifClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CMosBWellDifImpl.wpdifClass, WriteRectangle, ReadRectangle];
RegisterObjectClass[CDTexts.textClass, WriteFlipText, ReadFlipText];