/// <summary> /// Add cases to a union node in the treeview from loaded document. /// </summary> /// <remarks> /// The TypeNode for UnionCase object node has null reference for DataNode. /// TODO: union containing arrays not supported here /// </remarks> /// <param name="node"></param> /// <param name="t"></param> protected void addUnionNode(TreeNode node, UnionNode t) { foreach (CaseNode c in t.getCases()) { DataNode dt = new DataNode(c); node.Nodes.Add(dt); //node.LastNode.Text = c.toNodeText(); AbstractNode caseBody = c.getCaseBody(); TreeNode caseNode = node.LastNode; caseNode.Nodes.Add(new DataNode(caseBody)); if (caseBody.isComplex()) { if (caseBody.GetType().Equals(typeof(StructNode))) { addStructNode(caseNode.LastNode, (StructNode)caseBody); } else if (caseBody.GetType().Equals(typeof(UnionNode))) { addUnionNode(caseNode.LastNode, (UnionNode)caseBody); } else if (caseBody.GetType().Equals(typeof(ArrayNode))) { addArrayNode(caseNode.LastNode, (ArrayNode)caseBody); } } } }
/// <summary> /// Parse and load a union element type /// </summary> /// <param name="reader"></param> /// <returns></returns> protected static UnionNode LoadUnion(XmlTextReader reader) { string vname = reader.GetAttribute("varName"); string blocksize = reader.GetAttribute("blockSize"); UnionNode ut = new UnionNode(); if (vname != null) { ut.setVarName( vname ); } if (blocksize != null) { ut.setBlockSize( Convert.ToInt32(blocksize) ); } bool inDiscriminantSection = false; bool inCaseSection = false; string dv = null; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (reader.LocalName.Equals("discriminant")) { inDiscriminantSection = true; } else if (reader.LocalName.Equals("case")) { inCaseSection = true; dv = reader.GetAttribute("discriminantValue"); } else { AbstractNode it = ParseNode(reader); if (inDiscriminantSection) { ut.setDiscriminantType( it.getTypeName() ); } else if (inCaseSection) { CaseNode c = new CaseNode(dv, it); ut.addCase(c); } } } else if (reader.NodeType == XmlNodeType.EndElement) { if (reader.LocalName.Equals("discriminant")) { inDiscriminantSection = false; } else if (reader.LocalName.Equals("case")) { inCaseSection = false; } else if (reader.LocalName.Equals("union")) { break; } } } return ut; }
/// <summary> /// Add a union data element. /// </summary> /// <param name="parentNode">parent that contains this union element</param> /// <param name="at">position where the new node is inserted before</param> /// <param name="defineType">if true invokes a define union type window</param> public void addUnionTypeNode(DataNode parentNode, int at, bool defineType) { FormUnion formUnion = new FormUnion(); if (defineType) { formUnion.TypeName = "MyUnionType-" + Convert.ToString(++typeUnionCounter_); } else { formUnion.Text = "Build a union element"; formUnion.ChangeLabel("Var Name:"); formUnion.TypeName = "myUnion-" + Convert.ToString(parentNode.Nodes.Count); //TODO: check for duplicate name } formUnion.setDataTypeSource(document_.getTypeNames()); DialogResult r = formUnion.ShowDialog(view_); if (r==DialogResult.OK) { string varName = formUnion.TypeName; string discriminantType = formUnion.DiscriminantType; string blockSize = formUnion.BlockSize; int nBlockSize = 0; try { nBlockSize = Convert.ToInt32(blockSize); } catch (Exception ex) { Console.WriteLine(ex.Message); } UnionNode un = new UnionNode((defineType)?"":varName); un.setDiscriminantType(discriminantType); if (nBlockSize > 0) { un.setBlockSize(nBlockSize); } AbstractNode aNode = un; if (defineType) { aNode = new DefineTypeNode(formUnion.TypeName, un); } DataNode dn = new DataNode(aNode); int n = 0; foreach (ListViewItem itm in formUnion.getCases()) { string sval = itm.Text; string stype = itm.SubItems[1].Text; string svname = itm.SubItems[2].Text; if (!stype.Equals("")) { //create a CaseNode CaseNode cn = new CaseNode(sval, null); //add data object as child node and case body of the case node DataNode dcn = new DataNode(cn); addChildNode(dcn, stype, svname); addChildNode(dn, dcn, n++); } } addChildNode(parentNode, dn, at); document_.setModified(); parentNode.ExpandAll(); } }
/// <summary> /// Check struct, union and array node for useType references, duplicate union case values. /// </summary> /// <remarks> /// This check should apply to the following scenarios: /// <list> /// A struct contains two or more member elements that have the same variable name /// A struct contains a useType as its member or member of its member which referenced a undefined type /// A struct contains no member element /// A union contains no case element /// A union contains two or more cases with the same discriminant value /// A union contains a useType element in any of the case elements that referenced a undefined type /// An array contains no dimension element /// An streamed array contains more than one dim element /// An variable-sized array's first dim element has a count (should be zero) /// A fixed array contains a dim element with a zero count (should be greater than 0) /// An array contains useType element that referenced a undefined type /// An array contains a variable-sized construct in its element or embeded descedants. /// </list> /// </remarks> /// <param name="dataNode"></param> /// <param name="defs"></param> /// <param name="report"></param> private static void checkComplexType(ComplexNode dataNode, Hashtable defs, ArrayList report) { if (dataNode.GetType().Equals(typeof(StructNode))) { StructNode sNode = (StructNode)dataNode; if (sNode.getMemberCount() > 0) { Hashtable varNames = new Hashtable(); foreach (AbstractNode aNode in ((StructNode)dataNode).getMembers()) { //check duplicate variable names as warnings checkVarNames(aNode, varNames, report); checkUseType(aNode, defs, report); } } else { //empty struct report.Add("Warning: struct '" + sNode.toNodeText() + "' contains no member element."); } } else if (dataNode.GetType().Equals(typeof(UnionNode))) { UnionNode uNode = (UnionNode)dataNode; if (uNode.getCaseCount() > 0) { Hashtable cases = new Hashtable(); foreach (CaseNode cNode in uNode.getCases()) { //case values must be unique if (cases.Contains(cNode.getDiscriminantValue())) { report.Add("Error: duplicate case value '" + cNode.getDiscriminantValue() + "' at union type '" + dataNode.toNodeText() + "'."); } else { cases.Add(cNode.getDiscriminantValue(), cNode); } //if case body is useType, check type defs checkUseType(cNode.getCaseBody(), defs, report); } } else { report.Add("Warning: union '" + uNode.toNodeText() + "' contains no case element."); } } else if (dataNode.GetType().Equals(typeof(ArrayNode))) { ArrayNode arrayNode = (ArrayNode)dataNode; if (arrayNode.getDimension() == null) { report.Add("Error: Array '" + arrayNode.toNodeText() + "' has no dimension element."); } else { if (arrayNode.isArrayStreamed() && arrayNode.getDimensionCount() > 1) { report.Add("Warning: Streamed array contains more than one dimension."); } else if (arrayNode.isArrayFixed()) { for (DimNode dn = arrayNode.getDimension(); dn != null; dn = dn.getChild()) { if (dn.count() <= 0) { report.Add("Error: array dimension is of invalid size at '" + arrayNode.toNodeText() + "'."); } } } else { //first dim must be of 0 size DimNode dn = arrayNode.getDimension(); if (dn.count() > 0) { report.Add("Warning: first dimension count of a variable-sized array ignored at '" + arrayNode.toNodeText() + "'."); } for (dn = dn.getChild(); dn != null; dn = dn.getChild()) { if (dn.count() <= 0) { report.Add("Error: array dimension is of invalid size at '" + arrayNode.toNodeText() + "'."); } } } } checkUseType(arrayNode.getElement(), defs, report); //check for variable-sized construct contained in arrays checkVariableConstruct(arrayNode.getElement(), report); } }
/// <summary> /// Parse and load a union element type /// </summary> /// <param name="reader"></param> /// <returns></returns> protected static UnionNode LoadUnion(XmlTextReader reader) { string vname = reader.GetAttribute("varName"); string blocksize = reader.GetAttribute("blockSize"); UnionNode ut = new UnionNode(); if (vname != null) { ut.setVarName(vname); } if (blocksize != null) { ut.setBlockSize(Convert.ToInt32(blocksize)); } bool inDiscriminantSection = false; bool inCaseSection = false; string dv = null; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (reader.LocalName.Equals("discriminant")) { inDiscriminantSection = true; } else if (reader.LocalName.Equals("case")) { inCaseSection = true; dv = reader.GetAttribute("discriminantValue"); } else { AbstractNode it = ParseNode(reader); if (inDiscriminantSection) { ut.setDiscriminantType(it.getTypeName()); } else if (inCaseSection) { CaseNode c = new CaseNode(dv, it); ut.addCase(c); } } } else if (reader.NodeType == XmlNodeType.EndElement) { if (reader.LocalName.Equals("discriminant")) { inDiscriminantSection = false; } else if (reader.LocalName.Equals("case")) { inCaseSection = false; } else if (reader.LocalName.Equals("union")) { break; } } } return(ut); }
/// <summary> /// Add a union data element. /// </summary> /// <param name="parentNode">parent that contains this union element</param> /// <param name="at">position where the new node is inserted before</param> /// <param name="defineType">if true invokes a define union type window</param> public void addUnionTypeNode(DataNode parentNode, int at, bool defineType) { FormUnion formUnion = new FormUnion(); if (defineType) { formUnion.TypeName = "MyUnionType-" + Convert.ToString(++typeUnionCounter_); } else { formUnion.Text = "Build a union element"; formUnion.ChangeLabel("Var Name:"); formUnion.TypeName = "myUnion-" + Convert.ToString(parentNode.Nodes.Count); //TODO: check for duplicate name } formUnion.setDataTypeSource(document_.getTypeNames()); DialogResult r = formUnion.ShowDialog(view_); if (r == DialogResult.OK) { string varName = formUnion.TypeName; string discriminantType = formUnion.DiscriminantType; string blockSize = formUnion.BlockSize; int nBlockSize = 0; try { nBlockSize = Convert.ToInt32(blockSize); } catch (Exception ex) { Console.WriteLine(ex.Message); } UnionNode un = new UnionNode((defineType)?"":varName); un.setDiscriminantType(discriminantType); if (nBlockSize > 0) { un.setBlockSize(nBlockSize); } AbstractNode aNode = un; if (defineType) { aNode = new DefineTypeNode(formUnion.TypeName, un); } DataNode dn = new DataNode(aNode); int n = 0; foreach (ListViewItem itm in formUnion.getCases()) { string sval = itm.Text; string stype = itm.SubItems[1].Text; string svname = itm.SubItems[2].Text; if (!stype.Equals("")) { //create a CaseNode CaseNode cn = new CaseNode(sval, null); //add data object as child node and case body of the case node DataNode dcn = new DataNode(cn); addChildNode(dcn, stype, svname); addChildNode(dn, dcn, n++); } } addChildNode(parentNode, dn, at); document_.setModified(); parentNode.ExpandAll(); } }