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 }