private void ReadRegions(Resource rsrc) { UInt32 regions = reader.ReadUInt32(); for (UInt32 i = 0; i < regions; i++) { UInt32 regionNameId = reader.ReadUInt32(); UInt32 regionOffset = reader.ReadUInt32(); Region rgn = new Region(); rgn.RegionName = staticStrings[regionNameId]; var lastRegionPos = stream.Position; stream.Seek(regionOffset, SeekOrigin.Begin); ReadNode(rgn); rsrc.Regions[rgn.RegionName] = rgn; stream.Seek(lastRegionPos, SeekOrigin.Begin); } }
public Resource Read() { using (this.reader = XmlReader.Create(stream)) { Resource rsrc = new Resource(); Region currentRegion = null; List<Node> stack = new List<Node>(); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { case "save": // Root element if (stack.Count() > 0) throw new InvalidFormatException("Node <save> was unexpected."); break; case "header": // LSX metadata part 1 string version = reader["version"]; if (version != InitialVersion && version != CurrentVersion) throw new InvalidFormatException(String.Format("Unsupported LSX version; expected {0}, found {1}", CurrentVersion, version)); rsrc.Metadata.timestamp = Convert.ToUInt64(reader["timestamp"]); break; case "version": // LSX metadata part 2 rsrc.Metadata.majorVersion = Convert.ToUInt32(reader["major"]); rsrc.Metadata.minorVersion = Convert.ToUInt32(reader["minor"]); rsrc.Metadata.revision = Convert.ToUInt32(reader["revision"]); rsrc.Metadata.buildNumber = Convert.ToUInt32(reader["build"]); break; case "region": if (currentRegion != null) throw new InvalidFormatException("A <region> can only start at the root level of a resource."); Debug.Assert(!reader.IsEmptyElement); var region = new Region(); region.RegionName = reader["id"]; Debug.Assert(region.RegionName != null); rsrc.Regions.Add(region.RegionName, region); currentRegion = region; break; case "node": if (currentRegion == null) throw new InvalidFormatException("A <node> must be located inside a region."); Node node; if (stack.Count() == 0) { // The node is the root node of the region node = currentRegion; } else { // New node under the current parent node = new Node(); node.Parent = stack.Last(); } node.Name = reader["id"]; Debug.Assert(node.Name != null); if (node.Parent != null) node.Parent.AppendChild(node); if (!reader.IsEmptyElement) stack.Add(node); break; case "attribute": var attrTypeId = Convert.ToUInt32(reader["type"]); var attrName = reader["id"]; var attrValue = reader["value"]; if (attrTypeId > (int)NodeAttribute.DataType.DT_Max) throw new InvalidFormatException(String.Format("Unsupported attribute data type: {0}", attrTypeId)); Debug.Assert(attrName != null); Debug.Assert(attrValue != null); var attr = new NodeAttribute((NodeAttribute.DataType)attrTypeId); attr.FromString(attrValue); if (attr.Type == NodeAttribute.DataType.DT_TranslatedString) { ((TranslatedString)attr.Value).Handle = reader["handle"]; Debug.Assert(((TranslatedString)attr.Value).Handle != null); } stack.Last().Attributes.Add(attrName, attr); break; case "children": // Child nodes are handled in the "node" case break; default: throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name)); } } else if (reader.NodeType == XmlNodeType.EndElement) { switch (reader.Name) { case "save": case "header": case "version": case "attribute": case "children": // These elements don't change the stack, just discard them break; case "region": Debug.Assert(stack.Count == 0); Debug.Assert(currentRegion != null); Debug.Assert(currentRegion.Name != null); currentRegion = null; break; case "node": stack.RemoveAt(stack.Count - 1); break; default: throw new InvalidFormatException(String.Format("Unknown element encountered: {0}", reader.Name)); } } } return rsrc; } }