/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: JELIB.java
* Input/output tool: JELIB Library output
* Written by Steven M. Rubin, Sun Microsystems.
*
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.io.output;
import com.sun.electric.database.CellBackup;
import com.sun.electric.database.CellRevision;
import com.sun.electric.database.ImmutableArcInst;
import com.sun.electric.database.ImmutableCell;
import com.sun.electric.database.ImmutableElectricObject;
import com.sun.electric.database.ImmutableExport;
import com.sun.electric.database.ImmutableIconInst;
import com.sun.electric.database.ImmutableNodeInst;
import com.sun.electric.database.LibraryBackup;
import com.sun.electric.database.Snapshot;
import com.sun.electric.database.geometry.EPoint;
import com.sun.electric.database.hierarchy.Cell;
import com.sun.electric.database.hierarchy.View;
import com.sun.electric.database.id.ArcProtoId;
import com.sun.electric.database.id.CellId;
import com.sun.electric.database.id.CellUsage;
import com.sun.electric.database.id.ExportId;
import com.sun.electric.database.id.LibId;
import com.sun.electric.database.id.NodeProtoId;
import com.sun.electric.database.id.PortProtoId;
import com.sun.electric.database.id.PrimitiveNodeId;
import com.sun.electric.database.id.TechId;
import com.sun.electric.database.text.CellName;
import com.sun.electric.database.text.Name;
import com.sun.electric.database.text.Setting;
import com.sun.electric.database.text.Version;
import com.sun.electric.database.variable.CodeExpression;
import com.sun.electric.database.variable.TextDescriptor;
import com.sun.electric.database.variable.Variable;
import com.sun.electric.technology.Technology;
import com.sun.electric.tool.Tool;
import com.sun.electric.util.TextUtils;
import com.sun.electric.util.math.DBMath;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Class to write a library to disk in new Electric-Library format.
*/
public class JELIB extends Output {
private boolean oldRevision;
private Version version;
/** Project preferences. */ private HashMap<Setting,Object> projectSettings = new HashMap<Setting,Object>();
// private Map<LibId,URL> libFiles;
JELIB() {
}
/**
* Method to write a Library in Electric Library (.jelib) format.
* @param snapshot snapshot of the Library
* @param libId Id of the Library to be written.
* @param libFiles new locations of lib files
* @param oldRevision true to write library in format prior to "8.04l".
* @return true on error.
*/
protected boolean writeLib(Snapshot snapshot, LibId libId, Map<LibId,URL> libFiles, boolean oldRevision) {
this.oldRevision = oldRevision;
version = oldRevision ? Version.parseVersion("8.03") : Version.getVersion();
// this.libFiles = libFiles;
writeTheLibrary(snapshot, libId);
return false;
}
/**
* Method to write the .jelib file.
* @param snapshot snapshot of the Library
* @param libId Id of the Library to be written.
*/
private void writeTheLibrary(Snapshot snapshot, LibId libId)
{
// gather all referenced objects
// this.snapshot = snapshot;
LibraryBackup libBackup = snapshot.getLib(libId);
HashSet<CellId> usedCells = new HashSet<CellId>();
TreeMap<CellName,CellRevision> sortedCells = new TreeMap<CellName,CellRevision>();
for (CellBackup cellBackup: snapshot.cellBackups) {
if (cellBackup == null) continue;
CellRevision cellRevision = cellBackup.cellRevision;
if (cellRevision.d.getLibId() != libId) continue;
CellId cellId = cellRevision.d.cellId;
sortedCells.put(cellId.cellName, cellRevision);
int[] instCounts = cellRevision.getInstCounts();
for (int i = 0; i < instCounts.length; i++) {
int instCount = instCounts[i];
if (instCount == 0) continue;
CellUsage u = cellId.getUsageIn(i);
usedCells.add(u.protoId);
}
}
HashSet<LibId> usedLibs = new HashSet<LibId>();
for (CellId cellId: usedCells)
usedLibs.add(cellId.libId);
// write header information (library, version)
printWriter.println("# header information:");
printWriter.print("H" + convertString(libBackup.d.libId.libName) + "|" + version.toOldStyleString());
printlnVars(libBackup.d);
// write view information
boolean viewHeaderPrinted = false;
HashSet<View> usedViews = new HashSet<View>();
for (CellBackup cellBackup: snapshot.cellBackups) {
if (cellBackup == null) continue;
CellRevision cellRevision = cellBackup.cellRevision;
if (cellRevision.d.getLibId() != libId && !usedCells.contains(cellRevision.d.cellId)) continue;
usedViews.add(cellRevision.d.cellId.cellName.getView());
}
for(Iterator<View> it = View.getViews(); it.hasNext(); ) {
View view = it.next();
if (!usedViews.contains(view)) continue;
if (!viewHeaderPrinted) {
printWriter.println();
printWriter.println("# Views:");
viewHeaderPrinted = true;
}
printWriter.println("V" + convertString(view.getFullName()) + "|" + convertString(view.getAbbreviation()));
}
// write external library information
writeExternalLibraryInfo(libId, usedLibs);
Map<Setting,Object> snapshotSettings = snapshot.getSettings();
// write tool information
boolean toolHeaderPrinted = false;
for(Iterator<Tool> it = Tool.getTools(); it.hasNext(); ) {
Tool tool = it.next();
Map<Setting,Object> settings = tool.getProjectSettings().getDiskSettings(snapshotSettings);
if (settings.isEmpty()) continue;
if (!toolHeaderPrinted) {
printWriter.println();
printWriter.println("# Tools:");
toolHeaderPrinted = true;
}
printWriter.print("O" + convertString(tool.getName()));
printlnSettings(settings);
}
// write technology information
boolean technologyHeaderPrinted = false;
for (Iterator<Technology> it = Technology.getTechnologies(); it.hasNext(); ) {
Technology tech = it.next();
Map<Setting,Object> settings = tech.getProjectSettings().getDiskSettings(snapshotSettings);
if (settings.isEmpty()) continue;
if (!technologyHeaderPrinted) {
printWriter.println();
printWriter.println("# Technologies:");
technologyHeaderPrinted = true;
}
printWriter.print("T" + convertString(tech.getTechName()));
printlnSettings(settings);
}
// write cells
ArrayList<CellRevision> sortedCellsList = new ArrayList<CellRevision>(sortedCells.values());
snapshot.techPool.correctSizesToDisk(sortedCellsList, version, projectSettings, true, false);
for (CellRevision cellRevision: sortedCellsList) {
writeCell(cellRevision);
//printWriter.println();
}
// printWriter.println();
}
/**
* Method to write a cell to the output file
* @param cellRevision the cell to write
*/
void writeCell(CellRevision cellRevision) {
ImmutableCell d = cellRevision.d;
LibId libId = d.getLibId();
// write the Cell name
printWriter.println();
printWriter.println("# Cell " + d.cellId.cellName);
printWriter.print("C" + convertString(d.cellId.cellName.toString()));
if (!oldRevision) {
printWriter.print("|");
String cellGroupName = d.groupName.getName();
if (!cellGroupName.equals(d.cellId.cellName.getName()))
printWriter.print(convertString(cellGroupName));
}
printWriter.print("|" + convertString(d.techId.techName));
printWriter.print("|" + d.creationDate);
printWriter.print("|" + d.revisionDate);
StringBuilder cellBits = new StringBuilder();
if ((d.flags & Cell.INCELLLIBRARY) != 0) cellBits.append("C");
if ((d.flags & Cell.WANTNEXPAND) != 0 || d.cellId.isIcon()) cellBits.append("E");
if ((d.flags & Cell.NPILOCKED) != 0) cellBits.append("I");
if ((d.flags & Cell.NPLOCKED) != 0) cellBits.append("L");
if ((d.flags & Cell.TECEDITCELL) != 0) cellBits.append("T");
printWriter.print("|" + cellBits.toString());
printlnVars(d);
ArrayList<String> nodeNames = new ArrayList<String>();
// write the nodes in this cell (sorted by node name)
Name prevNodeName = null;
int duplicate = 0;
for (ImmutableNodeInst n: cellRevision.nodes) {
NodeProtoId np = n.protoId;
if (np instanceof CellId) {
CellId subCellId = (CellId)np;
String subCellName = subCellId.libId == libId ? subCellId.cellName.toString() : subCellId.toString();
printWriter.print("I" + convertString(subCellName));
} else {
PrimitiveNodeId primId = (PrimitiveNodeId)np;
if (d.techId == primId.techId)
printWriter.print("N" + convertString(primId.name));
else
printWriter.print("N" + convertString(primId.fullName));
}
String diskNodeName;
if (n.name != prevNodeName) {
prevNodeName = n.name;
duplicate = 0;
diskNodeName = convertString(n.name.toString());
} else {
duplicate++;
diskNodeName = "\"" + convertQuotedString(n.name.toString()) + "\"" + duplicate;
}
int nodeId = n.nodeId;
while (nodeId >= nodeNames.size()) nodeNames.add(null);
nodeNames.set(nodeId, diskNodeName);
printWriter.print("|" + diskNodeName + "|");
if (!n.name.isTempname())
printWriter.print(describeDescriptor(n.nameDescriptor));
printWriter.print("|" + TextUtils.formatDouble(n.anchor.getX(), 0));
printWriter.print("|" + TextUtils.formatDouble(n.anchor.getY(), 0));
if (!(np instanceof CellId)) {
double lambdaWidth = n.size.getLambdaX();
double lambdaHeight = n.size.getLambdaY();
printWriter.print("|");
if (lambdaWidth != 0)
printWriter.print(TextUtils.formatDouble(lambdaWidth, 0));
printWriter.print("|");
if (lambdaHeight != 0)
printWriter.print(TextUtils.formatDouble(lambdaHeight, 0));
}
printWriter.print('|');
if (n.orient.isXMirrored()) printWriter.print('X');
if (n.orient.isYMirrored()) printWriter.print('Y');
int angle = n.orient.getAngle() % 3600;
if (angle == 900 || angle == -2700) printWriter.print("R");
else if (angle == 1800 || angle == -1800) printWriter.print("RR");
else if (angle == 2700 || angle == -900) printWriter.print("RRR");
else if (angle != 0) printWriter.print(angle);
StringBuilder nodeBits = new StringBuilder();
if (n.is(ImmutableNodeInst.HARD_SELECT)) nodeBits.append("A");
if (n.is(ImmutableNodeInst.LOCKED)) nodeBits.append("L");
if (n.is(ImmutableNodeInst.VIS_INSIDE)) nodeBits.append("V");
int ts = n.techBits;
if (ts != 0) nodeBits.append(ts);
printWriter.print("|" + nodeBits.toString());
if (np instanceof CellId) {
String tdString = describeDescriptor(n.protoDescriptor);
printWriter.print("|" + tdString);
}
printlnVars(n);
}
// write the arcs in this cell
for (ImmutableArcInst a: cellRevision.arcs) {
ArcProtoId apId = a.protoId;
if (cellRevision.d.techId == apId.techId)
printWriter.print("A" + convertString(apId.name));
else
printWriter.print("A" + convertString(apId.fullName));
printWriter.print("|" + convertString(a.name.toString()) + "|");
if (!a.name.isTempname())
printWriter.print(describeDescriptor(a.nameDescriptor));
long arcWidth = a.getGridExtendOverMin()*2;
printWriter.print("|");
if (arcWidth != 0)
printWriter.print(TextUtils.formatDouble(DBMath.gridToLambda(arcWidth), 0));
StringBuilder arcBits = new StringBuilder();
if (a.is(ImmutableArcInst.HARD_SELECT)) arcBits.append("A");
if (a.is(ImmutableArcInst.BODY_ARROWED)) arcBits.append("B");
if (!a.is(ImmutableArcInst.FIXED_ANGLE)) arcBits.append("F");
if (a.is(ImmutableArcInst.HEAD_NEGATED)) arcBits.append("G");
if (!a.is(ImmutableArcInst.HEAD_EXTENDED)) arcBits.append("I");
if (!a.is(ImmutableArcInst.TAIL_EXTENDED)) arcBits.append("J");
if (a.is(ImmutableArcInst.TAIL_NEGATED)) arcBits.append("N");
if (a.is(ImmutableArcInst.RIGID)) arcBits.append("R");
if (a.is(ImmutableArcInst.SLIDABLE)) arcBits.append("S");
if (a.is(ImmutableArcInst.HEAD_ARROWED)) arcBits.append("X");
if (a.is(ImmutableArcInst.TAIL_ARROWED)) arcBits.append("Y");
String angle = "";
if (a.getAngle() != -1) angle += a.getAngle();
printWriter.print("|" + arcBits.toString() + angle);
printWriter.print("|" + nodeNames.get(a.headNodeId) + "|" + getPortName(a.headPortId));
printWriter.print("|" + TextUtils.formatDouble(a.headLocation.getX(), 0));
printWriter.print("|" + TextUtils.formatDouble(a.headLocation.getY(), 0));
printWriter.print("|" + nodeNames.get(a.tailNodeId) + "|" + getPortName(a.tailPortId));
printWriter.print("|" + TextUtils.formatDouble(a.tailLocation.getX(), 0));
printWriter.print("|" + TextUtils.formatDouble(a.tailLocation.getY(), 0));
printlnVars(a);
}
// write the exports in this cell
for (ImmutableExport e: cellRevision.exports) {
printWriter.print("E" + convertString(e.exportId.externalId));
if (!oldRevision) {
printWriter.print("|");
if (!e.name.toString().equals(e.exportId.externalId))
printWriter.print(convertString(e.name.toString()));
}
printWriter.print("|" + describeDescriptor(e.nameDescriptor));
printWriter.print("|" + nodeNames.get(e.originalNodeId) + "|" + getPortName(e.originalPortId));
printWriter.print("|" + e.characteristic.getShortName());
if (e.alwaysDrawn) printWriter.print("/A");
if (e.bodyOnly) printWriter.print("/B");
printlnVars(e);
}
// write the end-of-cell marker
printWriter.println("X");
}
void writeExternalLibraryInfo(LibId thisLib, Set<LibId> usedLibs) {
// write external library information
boolean libraryHeaderPrinted = false;
TreeMap<String,LibId> sortedLibraries = new TreeMap<String,LibId>(TextUtils.STRING_NUMBER_ORDER);
for (LibId libId: usedLibs)
sortedLibraries.put(libId.libName, libId);
for (LibId libId: sortedLibraries.values()) {
if (libId == thisLib) continue;
if (!libraryHeaderPrinted) {
printWriter.println();
printWriter.println("# External Libraries:");
libraryHeaderPrinted = true;
}
String libFile = libId.libName;
printWriter.println();
printWriter.println("L" + convertString(libId.libName) + "|" + convertString(libFile));
}
}
/**
* Helper method to convert a TextDescriptor to a string that describes it
*/
private String describeDescriptor(TextDescriptor td) {
return describeDescriptor(null, td, false);
}
/**
* Method to convert a variable to a string that describes its TextDescriptor
* @param var the Variable being described (may be null).
* @param td the TextDescriptor being described.
* @param isParam true to output parameter bit
* @return a String describing the variable/textdescriptor.
* The string has these fields:
* Asize; for absolute size
* B if bold
* Cindex; if color index
* Dx for display position (2=bottom 8=top 4=left 6=right 7=upleft 9=upright 1=downleft 3=downright 5=centered 0=boxed)
* FfontName; if a nonstandard font
* Gsize; for relative (grid unit) size
* H if inherit
* I if italic
* L if underline
* N if name=value;
* Ol for language (J=Java L=Lisp T=TCL)
* P if parameter
* R/RR/RRR if rotated (90, 180, 270)
* T if interior
* Ux for units (R=resistance C=capacitance I=inductance A=current V=voltage D=distance T=time)
* Xoffset; for X offset
* Yoffset; for Y offset
*/
public static String describeDescriptor(Variable var, TextDescriptor td, boolean isParam) {
StringBuilder ret = new StringBuilder();
TextDescriptor.Display display = td.getDisplay();
if (var == null) display = TextDescriptor.Display.SHOWN;
if (display != TextDescriptor.Display.NONE) {
// write size
TextDescriptor.Size size = td.getSize();
if (size.isAbsolute()) ret.append("A" + (int)size.getSize() + ";");
// write bold
if (td.isBold()) ret.append("B");
// write color
int color = td.getColorIndex();
if (color != 0)
ret.append("C" + color + ";");
// displayable: write display position
ret.append(display == TextDescriptor.Display.SHOWN ? "D" : "d");
TextDescriptor.Position pos = td.getPos();
if (pos == TextDescriptor.Position.UP) ret.append("8"); else
if (pos == TextDescriptor.Position.DOWN) ret.append("2"); else
if (pos == TextDescriptor.Position.LEFT) ret.append("4"); else
if (pos == TextDescriptor.Position.RIGHT) ret.append("6"); else
if (pos == TextDescriptor.Position.UPLEFT) ret.append("7"); else
if (pos == TextDescriptor.Position.UPRIGHT) ret.append("9"); else
if (pos == TextDescriptor.Position.DOWNLEFT) ret.append("1"); else
if (pos == TextDescriptor.Position.DOWNRIGHT) ret.append("3"); else
if (pos == TextDescriptor.Position.BOXED) ret.append("0"); else
ret.append("5");
// write font
int font = td.getFace();
if (font != 0) {
TextDescriptor.ActiveFont af = TextDescriptor.ActiveFont.findActiveFont(font);
ret.append("F" + convertString(af.toString()) + ";");
}
if (!size.isAbsolute()) ret.append("G" + TextUtils.formatDouble(size.getSize()) + ";");
}
// write inherit
if (td.isInherit()) ret.append("H");
if (display != TextDescriptor.Display.NONE) {
// write italic
if (td.isItalic()) ret.append("I");
// write underline
if (td.isUnderline()) ret.append("L");
// write display type
TextDescriptor.DispPos dispPos = td.getDispPart();
if (dispPos == TextDescriptor.DispPos.NAMEVALUE) ret.append("N");
}
// write language
if (var != null) {
switch (var.getCode()) {
case JAVA: ret.append("OJ"); break;
case SPICE: ret.append("OL"); break;
case TCL: ret.append("OT"); break;
case NONE: break;
default: throw new AssertionError();
}
}
// write parameter
if (isParam) ret.append("P");
if (display != TextDescriptor.Display.NONE) {
// write rotation
TextDescriptor.Rotation rot = td.getRotation();
if (rot == TextDescriptor.Rotation.ROT90) ret.append("R"); else
if (rot == TextDescriptor.Rotation.ROT180) ret.append("RR"); else
if (rot == TextDescriptor.Rotation.ROT270) ret.append("RRR");
}
// write interior
if (td.isInterior()) ret.append("T");
// write units
TextDescriptor.Unit unit = td.getUnit();
if (unit == TextDescriptor.Unit.RESISTANCE) ret.append("UR"); else
if (unit == TextDescriptor.Unit.CAPACITANCE) ret.append("UC"); else
if (unit == TextDescriptor.Unit.INDUCTANCE) ret.append("UI"); else
if (unit == TextDescriptor.Unit.CURRENT) ret.append("UA"); else
if (unit == TextDescriptor.Unit.VOLTAGE) ret.append("UV"); else
if (unit == TextDescriptor.Unit.DISTANCE) ret.append("UD"); else
if (unit == TextDescriptor.Unit.TIME) ret.append("UT");
if (display != TextDescriptor.Display.NONE) {
// write offset
double offX = td.getXOff();
if (offX != 0) ret.append("X" + TextUtils.formatDouble(offX, 0) + ";");
double offY = td.getYOff();
if (offY != 0) ret.append("Y" + TextUtils.formatDouble(offY, 0) + ";");
}
return ret.toString();
}
/**
* Method to write the variables on an ImmutableElectricObject.
* If object is ImmuatbleNodeInst write variables on its PortInsts also.
*/
private void printlnVars(ImmutableElectricObject d) {
// write the variables
if (d instanceof ImmutableNodeInst) {
if (d instanceof ImmutableIconInst) {
for (Iterator<Variable> it = ((ImmutableIconInst)d).getDefinedParameters(); it.hasNext(); )
printVar(null, it.next());
}
ImmutableNodeInst nid = (ImmutableNodeInst)d;
printVars(null, nid);
if (nid.hasPortInstVariables()) {
ArrayList<PortProtoId> portsWithVariables = new ArrayList<PortProtoId>();
for (Iterator<PortProtoId> it = nid.getPortsWithVariables(); it.hasNext(); )
portsWithVariables.add(it.next());
Collections.sort(portsWithVariables, PORTS_BY_EXTERNAL_ID);
for (PortProtoId portProtoId: portsWithVariables)
printVars(portProtoId.externalId, nid.getPortInst(portProtoId));
}
} else {
if (d instanceof ImmutableCell) {
for (Iterator<Variable> it = ((ImmutableCell)d).getParameters(); it.hasNext(); )
printVar(null, it.next());
}
printVars(null, d);
}
printWriter.println();
}
private static Comparator<PortProtoId> PORTS_BY_EXTERNAL_ID = new Comparator<PortProtoId>() {
public int compare(PortProtoId pp1, PortProtoId pp2) {
return TextUtils.STRING_NUMBER_ORDER.compare(pp1.externalId, pp2.externalId);
}
};
/**
* Method to write the variables on an object.
*/
private void printVars(String portName, ImmutableElectricObject d) {
// write the variables
for(Iterator<Variable> it = d.getVariables(); it.hasNext(); ) {
Variable var = it.next();
printVar(portName, var);
}
}
/**
* Method to write the variable on an object.
*/
private void printVar(String portName, Variable var) {
// write the variables
Object varObj = var.getObject();
TextDescriptor td = var.getTextDescriptor();
boolean isParam = td.isParam();
String tdString = describeDescriptor(var, td, isParam);
printWriter.print("|" + convertVariableName(diskName(portName, var)) + "(" + tdString + ")");
String pt = makeString(varObj);
if (pt == null) pt = "";
printWriter.print(pt);
}
/**
* Method to write the project preferences on an object.
*/
private void printlnSettings(Map<Setting,Object> settings) {
for (Map.Entry<Setting,Object> e: settings.entrySet()) {
Setting setting = e.getKey();
Object value = e.getValue();
projectSettings.put(setting, value);
printWriter.print("|" + convertVariableName(setting.getPrefName()) + "()" + makeString(value));
}
printWriter.println();
}
/**
* Method to convert variable "var" to a string for printing in the text file.
* returns zero on error
*/
private String makeString(Object obj) {
StringBuffer infstr = new StringBuffer();
char type = getVarType(obj);
infstr.append(type);
if (obj instanceof Object[]) {
Object [] objArray = (Object [])obj;
int len = objArray.length;
infstr.append('[');
for(int i=0; i<len; i++) {
Object oneObj = objArray[i];
if (i != 0) infstr.append(',');
makeStringVar(infstr, type, oneObj, true);
}
infstr.append(']');
} else {
makeStringVar(infstr, type, obj, false);
}
return infstr.toString();
}
/**
* Method to make a string from the value in "addr" which has a type in
* "type".
*/
private void makeStringVar(StringBuffer infstr, char type, Object obj, boolean inArray) {
if (obj == null) return;
switch (type) {
case 'B': infstr.append(((Boolean)obj).booleanValue() ? 'T' : 'F'); return;
case 'C': infstr.append(convertString(((CellId)obj).toString(), inArray)); return;
case 'D': infstr.append(((Double)obj).doubleValue()); return;
case 'E': infstr.append(convertString(((ExportId)obj).toString(), inArray)); return;
case 'F': infstr.append(((Float)obj).floatValue()); return;
case 'G': infstr.append(((Long)obj).longValue()); return;
case 'H': infstr.append(((Short)obj).shortValue()); return;
case 'I': infstr.append(((Integer)obj).intValue()); return;
case 'L': infstr.append(convertString(((LibId)obj).libName, inArray)); return;
case 'O': infstr.append(convertString(((Tool)obj).getName(), inArray)); return;
case 'P': infstr.append(convertString(((PrimitiveNodeId)obj).fullName, inArray)); return;
case 'R': infstr.append(convertString(((ArcProtoId)obj).fullName, inArray)); return;
case 'S': infstr.append(convertString(obj.toString(), inArray)); return;
case 'T': infstr.append(convertString(((TechId)obj).techName, inArray)); return;
case 'V': {
EPoint pt2 = (EPoint)obj;
infstr.append(TextUtils.formatDouble(pt2.getX(), 0) + "/" + TextUtils.formatDouble(pt2.getY(), 0));
return;
}
case 'Y': infstr.append(((Byte)obj).byteValue()); return;
}
}
private String getPortName(PortProtoId portId) {
String externalId = portId.externalId;
if (externalId.length() > 0)
externalId = convertString(externalId);
return externalId;
}
/**
* Method to make a char from the value in "addr" which has a type in
* "type".
*/
private char getVarType(Object obj) {
if (obj instanceof String || obj instanceof String []) return 'S';
if (obj instanceof CodeExpression) return 'S';
if (obj instanceof Boolean || obj instanceof Boolean []) return 'B';
if (obj instanceof CellId || obj instanceof CellId []) return 'C';
if (obj instanceof Double || obj instanceof Double []) return 'D';
if (obj instanceof ExportId || obj instanceof ExportId []) return 'E';
if (obj instanceof Float || obj instanceof Float []) return 'F';
if (obj instanceof Long || obj instanceof Long []) return 'G';
if (obj instanceof Short || obj instanceof Short []) return 'H';
if (obj instanceof Integer || obj instanceof Integer []) return 'I';
if (obj instanceof LibId || obj instanceof LibId []) return 'L';
if (obj instanceof Tool || obj instanceof Tool []) return 'O';
if (obj instanceof PrimitiveNodeId || obj instanceof PrimitiveNodeId []) return 'P';
if (obj instanceof ArcProtoId || obj instanceof ArcProtoId []) return 'R';
if (obj instanceof TechId || obj instanceof TechId []) return 'T';
if (obj instanceof EPoint || obj instanceof EPoint []) return 'V';
if (obj instanceof Byte || obj instanceof Byte []) return 'Y';
throw new AssertionError();
}
/**
* Method convert a string that is going to be quoted.
* Inserts the quote character (^) before any quotation character (') or quote character (^) in the string.
* Converts newlines to "^\n" (makeing the "\" and "n" separate characters).
* @param str the string to convert.
* @return the string with the appropriate quote characters.
* If no conversion is necessary, the input string is returned.
*/
private static String convertQuotedString(String str) {
StringBuffer infstr = new StringBuffer();
int len = str.length();
for(int i=0; i<len; i++) {
char ch = str.charAt(i);
if (ch == '\n') { infstr.append("\\n"); continue; }
if (ch == '\r') { infstr.append("\\r"); continue; }
if (ch == '"' || ch == '\\')
infstr.append('\\');
infstr.append(ch);
}
return infstr.toString();
}
/**
* Method convert a string that is not going to be quoted.
* Inserts a quote character (^) before any separator (|), quotation character (") or quote character (^) in the string.
* Converts newlines to spaces.
* @param str the string to convert.
* @return the string with the appropriate quote characters.
* If no conversion is necessary, the input string is returned.
*/
static String convertString(String str) {
return convertString(str, (char)0, (char)0);
}
/**
* Method convert a string that is not going to be quoted.
* Inserts a quote character (^) before any separator (|), quotation character (") or quote character (^) in the string.
* Converts newlines to spaces.
* @param str the string to convert.
* @return the string with the appropriate quote characters.
* If no conversion is necessary, the input string is returned.
*/
private static String convertString(String str, char delim1, char delim2) {
if (str.length() != 0 &&
str.indexOf('\n') < 0 &&
str.indexOf('\r') < 0 &&
str.indexOf('\\') < 0 &&
str.indexOf('"') < 0 &&
str.indexOf('|') < 0 &&
(delim1 == 0 || str.indexOf(delim1) < 0) &&
(delim2 == 0 || str.indexOf(delim2) < 0))
return str;
return '"' + convertQuotedString(str) + '"';
}
/**
* Method convert a string that is a variable name.
* If string contains end-of-lines, backslashes, bars, quotation characters, open parenthesis,
* encloses string in quotational characters.
* @param str the string to convert.
* @return the string with the appropriate quote characters.
* If no conversion is necessary, the input string is returned.
*/
private String convertVariableName(String str) {
return convertString(str, '(', (char)0);
}
/**
* Method convert a string that is a variable value.
* If string contains end-of-lines, backslashes, bars, quotation characters, comma,
* close bracket, returns string enclosed in quotational characters.
* @param str the string to convert.
* @param inArray true if string is element of array/
* @return the string with the appropriate quote characters.
* If no conversion is necessary, the input string is returned.
*/
private String convertString(String str, boolean inArray) {
return inArray ? convertString(str, ',', ']') : convertString(str, (char)0, (char)0);
}
}