/// <summary> /// Check to see whether there's variable-sized construct in an array. These include arrayVariable, arrayStreamed, union, string. /// </summary> /// <remarks> /// This check should apply to the following scenarios: /// <list> /// Arrays contain arrayVariable, arrayStreamed, or union /// Arrays contain struct which contains any of the above three elements /// Arrays contain a number of embedded structs at least one of which contains any of the above three elements /// Arrays contain arrayFixed which contains one of the above as element /// Arrays contain a number of embedded arrayFixed any of which contains any of the above three elements /// </list> /// </remarks> /// <param name="node"></param> /// <param name="report"></param> private static void checkVariableConstruct(AbstractNode node, ArrayList report) { if (node.GetType().Equals(typeof(StructNode))) { foreach (AbstractNode aNode in ((StructNode)node).getMembers()) { if (aNode.isComplex()) { checkVariableConstruct(aNode, report); } } } else if (node.GetType().Equals(typeof(UnionNode))) { report.Add("Warning: BinX library version 1.x does not support arrays containing union [" + node.toNodeText() + "]."); } else if (node.GetType().Equals(typeof(ArrayNode))) { ArrayNode aNode = (ArrayNode)node; if (aNode.isArrayFixed() == false) { report.Add("Warning: BinX library version 1.x does not support arrays containing variable-sized arrays [" + aNode.toNodeText() + "]."); } else { checkVariableConstruct(aNode.getElement(), report); } } }
/// <summary> /// Add array element to the array node in the treeview from loaded document. /// TODO: no support for array containing arrays or unions /// </summary> /// <param name="node"></param> /// <param name="t"></param> protected void addArrayNode(TreeNode node, ArrayNode t) { DataNode dt = new DataNode(t.getElement()); node.Nodes.Add(dt); if (t.getElement().isComplex()) { ComplexNode ct = (ComplexNode)t.getElement(); if (ct.GetType().Equals(typeof(StructNode))) { addStructNode(node.LastNode, (StructNode)ct); } else if (ct.GetType().Equals(typeof(ArrayNode))) { addArrayNode(node.LastNode, (ArrayNode)ct); } else if (ct.GetType().Equals(typeof(UnionNode))) { addUnionNode(node.LastNode, (UnionNode)ct); } } // add dims DataNode lastNode = (DataNode)node; DimNode dim = t.getDimension(); while (dim != null) { DataNode d = new DataNode(dim); lastNode.Nodes.Add(d); lastNode = d; dim = dim.getChild(); } }
/// <summary> /// Add an array data element. /// </summary> /// <param name="parentNode">parent node that contains this new node</param> /// <param name="at">position before which the new node is inserted</param> public void addArrayTypeNode(DataNode parentNode, int at, bool defineType) { FormArray formArray = new FormArray(); if (!defineType) { formArray.Text = "Build an array element"; formArray.ChangeLabel("Var Name:"); formArray.TypeName = "myArray-" + Convert.ToString(parentNode.Nodes.Count); //TODO: check for duplicate names } else { formArray.TypeName = "MyArray-" + Convert.ToString(++typeArrayCounter_); } formArray.DataTypeSource = document_.getTypeNames(); DialogResult r = formArray.ShowDialog(view_); if (r == DialogResult.OK) { string varName = formArray.TypeName; string arrayType = formArray.ArrayTypeName; ArrayNode an = new ArrayNode(arrayType, (defineType)?"":varName); //if variable, add sizeRef if (formArray.ArrayType == 2) { AbstractNode data = new PrimitiveNode(formArray.SizeRef); an.setSizeRef( data ); } AbstractNode aNode = an; if (defineType) { aNode = new DefineTypeNode(formArray.TypeName, an); } DataNode dn = new DataNode(aNode); addChildNode(dn, formArray.DataType, ""); //element data type as first child node of array if (formArray.ArrayType == 3) //arrayStreamed containing only one dim { //an.addDimension("", 0); addChildNode(dn, new DataNode(new DimNode("", 0)), 1); //dim as second child node of array } else //fixed or variable { DataNode tmpNode = dn; foreach (ListViewItem itm in formArray.getDimensions()) { string scount = itm.Text; string sdimname = itm.SubItems[1].Text; if (!scount.Equals("")) { //DataNode dNode = new DataNode(an.addDimension(sdimname, scount)); DataNode dNode = new DataNode(new DimNode(sdimname, scount)); addChildNode(tmpNode, dNode, 1); tmpNode = dNode; } } } addChildNode(parentNode, dn, at); document_.setModified(); parentNode.ExpandAll(); } }
/// <summary> /// Parse and load an array element type /// </summary> /// <param name="reader"></param> /// <returns></returns> protected static ArrayNode LoadArray(XmlTextReader reader) { string aname = reader.LocalName; string vname = reader.GetAttribute("varName"); string blocksize = reader.GetAttribute("blockSize"); ArrayNode a = new ArrayNode(aname); if (vname != null) { a.setVarName( vname ); } if (blocksize != null) { a.setBlockSize( Convert.ToInt32(blocksize) ); } bool inSizeRefSection = false; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (reader.LocalName.Equals("sizeRef")) { inSizeRefSection = true; } else if (reader.LocalName.Equals("dim")) { string dname = reader.GetAttribute("name"); int nCount = 0; string indexTo = reader.GetAttribute("indexTo"); if (indexTo == null) { string count = reader.GetAttribute("count"); if (count != null) { nCount = Convert.ToInt32(count); } } else { nCount = Convert.ToInt32(indexTo) + 1; } a.addDimension(dname, nCount); } else if (inSizeRefSection) { a.setSizeRef( ParseNode(reader) ); } else { a.setElement( ParseNode(reader) ); } } else if (reader.NodeType == XmlNodeType.EndElement) { if (reader.LocalName.Equals("sizeRef")) { inSizeRefSection = false; } else if (reader.LocalName.StartsWith("array")) { break; } } } return a; }
/// <summary> /// Add array element to the array node in the treeview from loaded document. /// TODO: no support for array containing arrays or unions /// </summary> /// <param name="node"></param> /// <param name="t"></param> protected void addArrayNode(TreeNode node, ArrayNode t) { DataNode dt = new DataNode( t.getElement() ); node.Nodes.Add(dt); if (t.getElement().isComplex()) { ComplexNode ct = (ComplexNode)t.getElement(); if (ct.GetType().Equals(typeof(StructNode))) { addStructNode(node.LastNode, (StructNode)ct); } else if (ct.GetType().Equals(typeof(ArrayNode))) { addArrayNode(node.LastNode, (ArrayNode)ct); } else if (ct.GetType().Equals(typeof(UnionNode))) { addUnionNode(node.LastNode, (UnionNode)ct); } } // add dims DataNode lastNode = (DataNode)node; DimNode dim = t.getDimension(); while (dim != null) { DataNode d = new DataNode(dim); lastNode.Nodes.Add(d); lastNode = d; dim = dim.getChild(); } }
/// <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 an array element type /// </summary> /// <param name="reader"></param> /// <returns></returns> protected static ArrayNode LoadArray(XmlTextReader reader) { string aname = reader.LocalName; string vname = reader.GetAttribute("varName"); string blocksize = reader.GetAttribute("blockSize"); ArrayNode a = new ArrayNode(aname); if (vname != null) { a.setVarName(vname); } if (blocksize != null) { a.setBlockSize(Convert.ToInt32(blocksize)); } bool inSizeRefSection = false; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (reader.LocalName.Equals("sizeRef")) { inSizeRefSection = true; } else if (reader.LocalName.Equals("dim")) { string dname = reader.GetAttribute("name"); int nCount = 0; string indexTo = reader.GetAttribute("indexTo"); if (indexTo == null) { string count = reader.GetAttribute("count"); if (count != null) { nCount = Convert.ToInt32(count); } } else { nCount = Convert.ToInt32(indexTo) + 1; } a.addDimension(dname, nCount); } else if (inSizeRefSection) { a.setSizeRef(ParseNode(reader)); } else { a.setElement(ParseNode(reader)); } } else if (reader.NodeType == XmlNodeType.EndElement) { if (reader.LocalName.Equals("sizeRef")) { inSizeRefSection = false; } else if (reader.LocalName.StartsWith("array")) { break; } } } return(a); }
/// <summary> /// Add an array data element. /// </summary> /// <param name="parentNode">parent node that contains this new node</param> /// <param name="at">position before which the new node is inserted</param> public void addArrayTypeNode(DataNode parentNode, int at, bool defineType) { FormArray formArray = new FormArray(); if (!defineType) { formArray.Text = "Build an array element"; formArray.ChangeLabel("Var Name:"); formArray.TypeName = "myArray-" + Convert.ToString(parentNode.Nodes.Count); //TODO: check for duplicate names } else { formArray.TypeName = "MyArray-" + Convert.ToString(++typeArrayCounter_); } formArray.DataTypeSource = document_.getTypeNames(); DialogResult r = formArray.ShowDialog(view_); if (r == DialogResult.OK) { string varName = formArray.TypeName; string arrayType = formArray.ArrayTypeName; ArrayNode an = new ArrayNode(arrayType, (defineType)?"":varName); //if variable, add sizeRef if (formArray.ArrayType == 2) { AbstractNode data = new PrimitiveNode(formArray.SizeRef); an.setSizeRef(data); } AbstractNode aNode = an; if (defineType) { aNode = new DefineTypeNode(formArray.TypeName, an); } DataNode dn = new DataNode(aNode); addChildNode(dn, formArray.DataType, ""); //element data type as first child node of array if (formArray.ArrayType == 3) //arrayStreamed containing only one dim { //an.addDimension("", 0); addChildNode(dn, new DataNode(new DimNode("", 0)), 1); //dim as second child node of array } else //fixed or variable { DataNode tmpNode = dn; foreach (ListViewItem itm in formArray.getDimensions()) { string scount = itm.Text; string sdimname = itm.SubItems[1].Text; if (!scount.Equals("")) { //DataNode dNode = new DataNode(an.addDimension(sdimname, scount)); DataNode dNode = new DataNode(new DimNode(sdimname, scount)); addChildNode(tmpNode, dNode, 1); tmpNode = dNode; } } } addChildNode(parentNode, dn, at); document_.setModified(); parentNode.ExpandAll(); } }