File indexing completed on 2024-12-15 04:19:54
0001 package mso.generator.utils; 0002 0003 import java.io.IOException; 0004 import java.util.ArrayList; 0005 import java.util.List; 0006 import java.util.SortedSet; 0007 import java.util.TreeSet; 0008 import java.util.zip.CRC32; 0009 0010 import org.eclipse.jdt.annotation.Nullable; 0011 import org.w3c.dom.Element; 0012 import org.w3c.dom.NodeList; 0013 0014 public class Member { 0015 public final TypeRegistry registry; 0016 public final String name; 0017 private final String typeName; 0018 @Nullable 0019 public final String count; 0020 @Nullable 0021 public final String size; 0022 @Nullable 0023 public final String condition; 0024 public final boolean isArray; 0025 public final boolean isOptional; 0026 public final boolean isInteger; 0027 public final boolean isSimple; 0028 public final boolean isStruct; 0029 public final boolean isChoice; 0030 public final Limitation limitations[]; 0031 0032 private static final String HEXINDEX = "0123456789abcdef ABCDEF"; 0033 0034 private static byte[] hexToByte(String s) { 0035 int l = s.length() / 2; 0036 byte data[] = new byte[l]; 0037 int j = 0; 0038 0039 for (int i = 0; i < l; i++) { 0040 char c = s.charAt(j++); 0041 int n, b; 0042 0043 n = HEXINDEX.indexOf(c); 0044 b = (n & 0xf) << 4; 0045 c = s.charAt(j++); 0046 n = HEXINDEX.indexOf(c); 0047 b += (n & 0xf); 0048 data[i] = (byte) b; 0049 } 0050 return data; 0051 } 0052 0053 class ByteArray implements Comparable<ByteArray> { 0054 final byte data[]; 0055 0056 ByteArray(byte data[]) { 0057 this.data = data; 0058 } 0059 0060 public int compareTo(ByteArray o) { 0061 byte b[] = o.data; 0062 0063 for (int i = 0; i < data.length && i < b.length; i++) { 0064 if (b[i] != data[i]) { 0065 return data[i] - b[i]; 0066 } 0067 } 0068 return data.length - b.length; 0069 } 0070 0071 } 0072 0073 Member(TypeRegistry r, Element e) throws IOException { 0074 registry = r; 0075 name = e.getAttribute("name"); 0076 condition = (e.hasAttribute("condition")) ? e.getAttribute("condition") 0077 : null; 0078 count = (e.hasAttribute("count")) ? e.getAttribute("count") : null; 0079 size = (e.hasAttribute("size")) ? e.getAttribute("size") : null; 0080 0081 isOptional = e.hasAttribute("optional"); 0082 isArray = count != null || e.hasAttribute("array"); 0083 if (isOptional && isArray) { 0084 throw new IOException("Member " + name 0085 + " is optional and array, which is not allowed."); 0086 } 0087 if (e.hasAttribute("type")) { 0088 typeName = e.getAttribute("type"); 0089 isInteger = false; 0090 isSimple = false; 0091 isChoice = false; 0092 isStruct = true; 0093 } else if (e.getNodeName().equals("choice")) { 0094 NodeList l = e.getElementsByTagName("type"); 0095 String choiceName = ""; 0096 List<Struct> choices = new ArrayList<Struct>(); 0097 Element msoelement = (Element) e.getParentNode().getParentNode(); 0098 for (int i = 0; i < l.getLength(); ++i) { 0099 String type = ((Element) l.item(i)).getAttribute("type"); 0100 Element ce = getStructElement(msoelement, type); 0101 choiceName += type; 0102 Type t = registry.getType(ce.getAttribute("name")); 0103 if (t instanceof Struct) { 0104 choices.add((Struct) t); 0105 } else { 0106 choices.add(new Struct(registry, ce)); 0107 } 0108 } 0109 CRC32 crc = new CRC32(); 0110 crc.update(choiceName.getBytes()); 0111 choiceName = "choice" + crc.getValue(); 0112 typeName = choiceName; 0113 if (registry.getType(typeName) == null) { 0114 new Choice(registry, choiceName, choices, isOptional); 0115 } 0116 isInteger = false; 0117 isSimple = false; 0118 isChoice = true; 0119 isStruct = false; 0120 } else if (e.getNodeName().equals("fixedchoice")) { 0121 SortedSet<ByteArray> texts = new TreeSet<ByteArray>(); 0122 NodeList l = e.getElementsByTagName("text"); 0123 for (int i = 0; i < l.getLength(); ++i) { 0124 String text = ((Element) l.item(i)).getTextContent(); 0125 texts.add(new ByteArray(text.getBytes("UTF8"))); 0126 } 0127 l = e.getElementsByTagName("hex"); 0128 for (int i = 0; i < l.getLength(); ++i) { 0129 String hex = ((Element) l.item(i)).getTextContent(); 0130 texts.add(new ByteArray(hexToByte(hex))); 0131 } 0132 CRC32 crc = new CRC32(); 0133 for (ByteArray b : texts) { 0134 crc.update(b.data); 0135 } 0136 typeName = "fixedchoice" + crc.getValue(); 0137 0138 if (registry.getType(typeName) == null) { 0139 new FixedChoice(registry, typeName, texts, isOptional); 0140 } 0141 isInteger = false; 0142 isSimple = true; 0143 isChoice = true; 0144 isStruct = false; 0145 } else { 0146 typeName = e.getNodeName(); 0147 isInteger = typeName.startsWith("int") 0148 || typeName.startsWith("uint"); 0149 isSimple = true; 0150 isChoice = false; 0151 isStruct = false; 0152 } 0153 0154 List<Limitation> _limitations = new ArrayList<Limitation>(); 0155 NodeList l = e.getChildNodes(); 0156 for (int i = 0; i < l.getLength(); ++i) { 0157 if (l.item(i) instanceof Element) { 0158 _limitations.add(new Limitation((Element) l.item(i))); 0159 } 0160 } 0161 limitations = _limitations.toArray(new Limitation[0]); 0162 } 0163 0164 public Type type() { 0165 return registry.getType(typeName); 0166 } 0167 0168 private static Element getStructElement(Element mso, String typename) { 0169 NodeList l = mso.getElementsByTagName("struct"); 0170 for (int i = 0; i < l.getLength(); ++i) { 0171 Element e = (Element) l.item(i); 0172 if (e.getAttribute("name").equals(typename)) { 0173 return e; 0174 } 0175 } 0176 throw new NullPointerException( 0177 "No struct type with name " + typename + " can be found."); 0178 } 0179 0180 }