diff --git a/Substrate/SubstrateCS/Source/NBT/INBTObject.cs b/Substrate/SubstrateCS/Source/NBT/INBTObject.cs
new file mode 100644
index 0000000..57e8817
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/INBTObject.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Substrate.NBT
+{
+ ///
+ /// Defines methods for loading or extracting an NBT tree.
+ ///
+ /// Object type that supports this interface.
+ public interface INBTObject
+ {
+ ///
+ /// Attempt to load an NBT tree into the object without validation.
+ ///
+ /// The root node of an NBT tree.
+ /// The object returns itself on success, or null if the tree was unparsable.
+ T LoadTree (TagNode tree);
+
+ ///
+ /// Attempt to load an NBT tree into the object with validation.
+ ///
+ /// The root node of an NBT tree.
+ /// The object returns itself on success, or null if the tree failed validation.
+ T LoadTreeSafe (TagNode tree);
+
+ ///
+ /// Builds an NBT tree from the object's data.
+ ///
+ /// The root node of an NBT tree representing the object's data.
+ TagNode BuildTree ();
+
+ ///
+ /// Validate an NBT tree, usually against an object-supplied schema.
+ ///
+ /// The root node of an NBT tree.
+ /// Status indicating whether the tree was valid for this object.
+ bool ValidateTree (TagNode tree);
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/NBT.cs b/Substrate/SubstrateCS/Source/NBT/NBT.cs
index eb0a1a3..e33102b 100644
--- a/Substrate/SubstrateCS/Source/NBT/NBT.cs
+++ b/Substrate/SubstrateCS/Source/NBT/NBT.cs
@@ -8,40 +8,6 @@ namespace Substrate.NBT
{
using Substrate.Utility;
- ///
- /// Defines methods for loading or extracting an NBT tree.
- ///
- /// Object type that supports this interface.
- public interface INBTObject
- {
- ///
- /// Attempt to load an NBT tree into the object without validation.
- ///
- /// The root node of an NBT tree.
- /// The object returns itself on success, or null if the tree was unparsable.
- T LoadTree (TagNode tree);
-
- ///
- /// Attempt to load an NBT tree into the object with validation.
- ///
- /// The root node of an NBT tree.
- /// The object returns itself on success, or null if the tree failed validation.
- T LoadTreeSafe (TagNode tree);
-
- ///
- /// Builds an NBT tree from the object's data.
- ///
- /// The root node of an NBT tree representing the object's data.
- TagNode BuildTree ();
-
- ///
- /// Validate an NBT tree, usually against an object-supplied schema.
- ///
- /// The root node of an NBT tree.
- /// Status indicating whether the tree was valid for this object.
- bool ValidateTree (TagNode tree);
- }
-
///
/// Contains the root node of an NBT tree and handles IO of tree nodes.
///
diff --git a/Substrate/SubstrateCS/Source/NBT/NBTSchema.cs b/Substrate/SubstrateCS/Source/NBT/NBTSchema.cs
deleted file mode 100644
index 2f9bc19..0000000
--- a/Substrate/SubstrateCS/Source/NBT/NBTSchema.cs
+++ /dev/null
@@ -1,408 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Substrate.NBT
-{
- [Flags]
- public enum SchemaOptions
- {
- OPTIONAL = 0x1,
- CREATE_ON_MISSING = 0x2,
- }
-
- public abstract class SchemaNode
- {
- private string _name;
- private SchemaOptions _options;
-
- public string Name
- {
- get { return _name; }
- }
-
- public SchemaOptions Options
- {
- get { return _options; }
- }
-
- public SchemaNode (string name)
- {
- _name = name;
- }
-
- public SchemaNode (string name, SchemaOptions options)
- {
- _name = name;
- _options = options;
- }
-
- public virtual TagNode BuildDefaultTree ()
- {
- return null;
- }
- }
-
- public sealed class SchemaNodeScaler : SchemaNode
- {
- private TagType _type;
-
- public TagType Type
- {
- get { return _type; }
- }
-
- public SchemaNodeScaler (string name, TagType type)
- : base(name)
- {
- _type = type;
- }
-
- public SchemaNodeScaler (string name, TagType type, SchemaOptions options)
- : base(name, options)
- {
- _type = type;
- }
-
- public override TagNode BuildDefaultTree ()
- {
- switch (_type) {
- case TagType.TAG_STRING:
- return new TagNodeString();
-
- case TagType.TAG_BYTE:
- return new TagNodeByte();
-
- case TagType.TAG_SHORT:
- return new TagNodeShort();
-
- case TagType.TAG_INT:
- return new TagNodeInt();
-
- case TagType.TAG_LONG:
- return new TagNodeLong();
-
- case TagType.TAG_FLOAT:
- return new TagNodeFloat();
-
- case TagType.TAG_DOUBLE:
- return new TagNodeDouble();
- }
-
- return null;
- }
- }
-
- public sealed class SchemaNodeString : SchemaNode
- {
- private string _value = "";
- private int _length;
-
- public int Length
- {
- get { return _length; }
- }
-
- public string Value
- {
- get { return _value; }
- }
-
- public SchemaNodeString (string name, SchemaOptions options)
- : base(name, options)
- {
- }
-
- public SchemaNodeString (string name, string value)
- : base(name)
- {
- _value = value;
- }
-
- public SchemaNodeString (string name, int length)
- : base(name)
- {
- _length = length;
- }
-
- public override TagNode BuildDefaultTree ()
- {
- if (_value.Length > 0) {
- return new TagNodeString(_value);
- }
-
- return new TagNodeString();
- }
- }
-
- public sealed class SchemaNodeArray : SchemaNode
- {
- private int _length;
-
- public int Length
- {
- get { return _length; }
- }
-
- public SchemaNodeArray (string name)
- : base(name)
- {
- _length = 0;
- }
-
- public SchemaNodeArray (string name, SchemaOptions options)
- : base(name, options)
- {
- _length = 0;
- }
-
- public SchemaNodeArray (string name, int length)
- : base(name)
- {
- _length = length;
- }
-
- public SchemaNodeArray (string name, int length, SchemaOptions options)
- : base(name, options)
- {
- _length = length;
- }
-
- public override TagNode BuildDefaultTree ()
- {
- return new TagNodeByteArray(new byte[_length]);
- }
- }
-
- public sealed class SchemaNodeList : SchemaNode
- {
- private TagType _type;
- private int _length;
- private SchemaNode _subschema;
-
- public int Length
- {
- get { return _length; }
- }
-
- public TagType Type
- {
- get { return _type; }
- }
-
- public SchemaNode SubSchema
- {
- get { return _subschema; }
- }
-
- public SchemaNodeList (string name, TagType type)
- : base(name)
- {
- _type = type;
- }
-
- public SchemaNodeList (string name, TagType type, SchemaOptions options)
- : base(name, options)
- {
- _type = type;
- }
-
- public SchemaNodeList (string name, TagType type, int length)
- : base(name)
- {
- _type = type;
- _length = length;
- }
-
- public SchemaNodeList (string name, TagType type, int length, SchemaOptions options)
- : base(name, options)
- {
- _type = type;
- _length = length;
- }
-
- public SchemaNodeList (string name, TagType type, SchemaNode subschema)
- : base(name)
- {
- _type = type;
- _subschema = subschema;
- }
-
- public SchemaNodeList (string name, TagType type, SchemaNode subschema, SchemaOptions options)
- : base(name, options)
- {
- _type = type;
- _subschema = subschema;
- }
-
- public SchemaNodeList (string name, TagType type, int length, SchemaNode subschema)
- : base(name)
- {
- _type = type;
- _length = length;
- _subschema = subschema;
- }
-
- public SchemaNodeList (string name, TagType type, int length, SchemaNode subschema, SchemaOptions options)
- : base(name, options)
- {
- _type = type;
- _length = length;
- _subschema = subschema;
- }
-
- public override TagNode BuildDefaultTree ()
- {
- if (_length == 0) {
- return new TagNodeList(_type);
- }
-
- TagNodeList list = new TagNodeList(_type);
- for (int i = 0; i < _length; i++) {
- list.Add(_subschema.BuildDefaultTree());
- }
-
- return list;
- }
- }
-
- public sealed class SchemaNodeCompound : SchemaNode, ICollection
- {
- private List _subnodes;
-
- #region ICollection Members
-
- public void Add (SchemaNode item)
- {
- _subnodes.Add(item);
- }
-
- public void Clear ()
- {
- _subnodes.Clear();
- }
-
- public bool Contains (SchemaNode item)
- {
- return _subnodes.Contains(item);
- }
-
- public void CopyTo (SchemaNode[] array, int arrayIndex)
- {
- _subnodes.CopyTo(array, arrayIndex);
- }
-
- public int Count
- {
- get { return _subnodes.Count; }
- }
-
- public bool IsReadOnly
- {
- get { return false; }
- }
-
- public bool Remove (SchemaNode item)
- {
- return _subnodes.Remove(item);
- }
-
- #endregion
-
- #region IEnumerable Members
-
- public IEnumerator GetEnumerator ()
- {
- return _subnodes.GetEnumerator();
- }
-
- #endregion
-
- #region IEnumerable Members
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
- {
- return _subnodes.GetEnumerator();
- }
-
- #endregion
-
- public SchemaNodeCompound ()
- : base("")
- {
- _subnodes = new List();
- }
-
- public SchemaNodeCompound (SchemaOptions options)
- : base("", options)
- {
- _subnodes = new List();
- }
-
- public SchemaNodeCompound (string name)
- : base(name)
- {
- _subnodes = new List();
- }
-
- public SchemaNodeCompound (string name, SchemaOptions options)
- : base(name, options)
- {
- _subnodes = new List();
- }
-
- public SchemaNodeCompound (string name, SchemaNode subschema)
- : base(name)
- {
- _subnodes = new List();
-
- SchemaNodeCompound schema = subschema as SchemaNodeCompound;
- if (schema == null) {
- return;
- }
-
- foreach (SchemaNode node in schema._subnodes)
- {
- _subnodes.Add(node);
- }
- }
-
- public SchemaNodeCompound (string name, SchemaNode subschema, SchemaOptions options)
- : base(name, options)
- {
- _subnodes = new List();
-
- SchemaNodeCompound schema = subschema as SchemaNodeCompound;
- if (schema == null) {
- return;
- }
-
- foreach (SchemaNode node in schema._subnodes) {
- _subnodes.Add(node);
- }
- }
-
- public SchemaNodeCompound MergeInto (SchemaNodeCompound tree)
- {
- foreach (SchemaNode node in _subnodes) {
- SchemaNode f = tree._subnodes.Find(n => n.Name == node.Name);
- if (f != null) {
- continue;
- }
- tree.Add(node);
- }
-
- return tree;
- }
-
- public override TagNode BuildDefaultTree ()
- {
- TagNodeCompound list = new TagNodeCompound();
- foreach (SchemaNode node in _subnodes) {
- list[node.Name] = node.BuildDefaultTree();
- }
-
- return list;
- }
- }
-}
diff --git a/Substrate/SubstrateCS/Source/NBT/NBTVerifier.cs b/Substrate/SubstrateCS/Source/NBT/NBTVerifier.cs
index b2a4bce..af9690e 100644
--- a/Substrate/SubstrateCS/Source/NBT/NBTVerifier.cs
+++ b/Substrate/SubstrateCS/Source/NBT/NBTVerifier.cs
@@ -4,36 +4,86 @@ using System.Text;
namespace Substrate.NBT
{
- public delegate void MissingTagHandler (Object o, TagEventArgs e);
- public delegate void InvalidTagTypeHandler (Object o, TagEventArgs e);
- public delegate void InvalidTagValueHandler (Object o, TagEventArgs e);
+ using Substrate.Utility;
- public interface INBTVerifier
+ ///
+ /// Indicates how an event processor should respond to returning event handler.
+ ///
+ public enum TagEventCode
{
- event MissingTagHandler MissingTag;
- event InvalidTagTypeHandler InvalidTagType;
- event InvalidTagValueHandler InvalidTagValue;
+ ///
+ /// The event processor should process the next event in the chian.
+ ///
+ NEXT,
- bool Verify ();
+ ///
+ /// The event processor should ignore the verification failure and stop processing any remaining events.
+ ///
+ PASS,
+
+ ///
+ /// The event processor should fail and stop processing any remaining events.
+ ///
+ FAIL,
}
+ ///
+ /// Event arguments for failure events.
+ ///
public class TagEventArgs : EventArgs
{
- protected string _tagName;
- protected TagNode _tag;
- protected SchemaNode _schema;
+ private string _tagName;
+ private TagNode _parent;
+ private TagNode _tag;
+ private SchemaNode _schema;
+ ///
+ /// Gets the expected name of the referenced by this event.
+ ///
public string TagName
{
get { return _tagName; }
}
+ ///
+ /// Gets the parent of the referenced by this event, if it exists.
+ ///
+ public TagNode Parent
+ {
+ get { return _parent; }
+ }
+
+ ///
+ /// Gets the referenced by this event.
+ ///
+ public TagNode Tag
+ {
+ get { return _tag; }
+ }
+
+ ///
+ /// Gets the corresponding to the referenced by this event.
+ ///
+ public SchemaNode Schema
+ {
+ get { return _schema; }
+ }
+
+ ///
+ /// Constructs a new event argument set.
+ ///
+ /// The expected name of a .
public TagEventArgs (string tagName)
: base()
{
_tagName = tagName;
}
+ ///
+ /// Constructs a new event argument set.
+ ///
+ /// The expected name of a .
+ /// The involved in this event.
public TagEventArgs (string tagName, TagNode tag)
: base()
{
@@ -41,6 +91,11 @@ namespace Substrate.NBT
_tagName = tagName;
}
+ ///
+ /// Constructs a new event argument set.
+ ///
+ /// The corresponding to the involved in this event.
+ /// The involved in this event.
public TagEventArgs (SchemaNode schema, TagNode tag)
: base()
{
@@ -49,35 +104,55 @@ namespace Substrate.NBT
}
}
- public class NBTVerifier : INBTVerifier
+ ///
+ /// Verifies the integrity of an NBT tree against a schema definition.
+ ///
+ public class NBTVerifier
{
private TagNode _root;
private SchemaNode _schema;
- public event MissingTagHandler MissingTag;
- public event InvalidTagTypeHandler InvalidTagType;
- public event InvalidTagValueHandler InvalidTagValue;
+ ///
+ /// An event that gets fired whenever an expected is not found.
+ ///
+ public static event Func MissingTag;
+
+ ///
+ /// An event that gets fired whenever an expected is of the wrong type and cannot be cast.
+ ///
+ public static event Func InvalidTagType;
+
+ ///
+ /// An event that gets fired whenever an expected has a value that violates the schema.
+ ///
+ public static event Func InvalidTagValue;
private Dictionary _scratch = new Dictionary();
- public NBTVerifier () { }
-
+ ///
+ /// Constructs a new object for a given NBT tree and schema.
+ ///
+ /// A representing the root of an NBT tree.
+ /// A representing the root of a schema definition for the NBT tree.
public NBTVerifier (TagNode root, SchemaNode schema)
{
_root = root;
_schema = schema;
}
- public bool Verify ()
+ ///
+ /// Invokes the verifier.
+ ///
+ /// Status indicating whether the NBT tree is valid for the given schema.
+ public virtual bool Verify ()
{
- return Verify(_root, _schema);
+ return Verify(null, _root, _schema);
}
- private bool Verify (TagNode tag, SchemaNode schema)
+ private bool Verify (TagNode parent, TagNode tag, SchemaNode schema)
{
if (tag == null) {
- OnMissingTag(new TagEventArgs(schema.Name));
- return false;
+ return OnMissingTag(new TagEventArgs(schema.Name));
}
SchemaNodeScaler scaler = schema as SchemaNodeScaler;
@@ -105,14 +180,15 @@ namespace Substrate.NBT
return VerifyCompound(tag, compound);
}
- return false;
+ return OnInvalidTagType(new TagEventArgs(schema.Name, tag));
}
private bool VerifyScaler (TagNode tag, SchemaNodeScaler schema)
{
if (!tag.IsCastableTo(schema.Type)) {
- OnInvalidTagType(new TagEventArgs(schema.Name, tag));
- return false;
+ if (!OnInvalidTagType(new TagEventArgs(schema.Name, tag))) {
+ return false;
+ }
}
return true;
@@ -122,16 +198,19 @@ namespace Substrate.NBT
{
TagNodeString stag = tag as TagNodeString;
if (stag == null) {
- OnInvalidTagType(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagType(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
if (schema.Length > 0 && stag.Length > schema.Length) {
- OnInvalidTagValue(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
if (schema.Value != null && stag.Data != schema.Value) {
- OnInvalidTagValue(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
return true;
@@ -142,12 +221,14 @@ namespace Substrate.NBT
{
TagNodeByteArray atag = tag as TagNodeByteArray;
if (atag == null) {
- OnInvalidTagType(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagType(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
if (schema.Length > 0 && atag.Length != schema.Length) {
- OnInvalidTagValue(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
return true;
@@ -157,16 +238,19 @@ namespace Substrate.NBT
{
TagNodeList ltag = tag as TagNodeList;
if (ltag == null) {
- OnInvalidTagType(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagType(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
if (ltag.Count > 0 && ltag.ValueType != schema.Type) {
- OnInvalidTagValue(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
if (schema.Length > 0 && ltag.Count != schema.Length) {
- OnInvalidTagValue(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagValue(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
// Patch up empty lists
@@ -180,7 +264,7 @@ namespace Substrate.NBT
if (schema.SubSchema != null) {
foreach (TagNode v in ltag) {
- pass = Verify(v, schema.SubSchema) && pass;
+ pass = Verify(tag, v, schema.SubSchema) && pass;
}
}
@@ -191,8 +275,9 @@ namespace Substrate.NBT
{
TagNodeCompound ctag = tag as TagNodeCompound;
if (ctag == null) {
- OnInvalidTagType(new TagEventArgs(schema, tag));
- return false;
+ if (!OnInvalidTagType(new TagEventArgs(schema, tag))) {
+ return false;
+ }
}
bool pass = true;
@@ -211,7 +296,7 @@ namespace Substrate.NBT
}
}
- pass = Verify(value, node) && pass;
+ pass = Verify(tag, value, node) && pass;
}
foreach (KeyValuePair item in _scratch) {
@@ -225,25 +310,70 @@ namespace Substrate.NBT
#region Event Handlers
- protected void OnMissingTag (TagEventArgs e)
+ ///
+ /// Processes registered events for whenever an expected is not found.
+ ///
+ /// Arguments for this event.
+ /// Status indicating whether this event can be ignored.
+ protected virtual bool OnMissingTag (TagEventArgs e)
{
if (MissingTag != null) {
- MissingTag(this, e);
+ foreach (Func func in MissingTag.GetInvocationList()) {
+ TagEventCode code = func(e);
+ switch (code) {
+ case TagEventCode.FAIL:
+ return false;
+ case TagEventCode.PASS:
+ return true;
+ }
+ }
}
+
+ return false;
}
- protected void OnInvalidTagType (TagEventArgs e)
+ ///
+ /// Processes registered events for whenever an expected is of the wrong type and cannot be cast.
+ ///
+ /// Arguments for this event.
+ /// Status indicating whether this event can be ignored.
+ protected virtual bool OnInvalidTagType (TagEventArgs e)
{
if (InvalidTagType != null) {
- InvalidTagType(this, e);
+ foreach (Func func in InvalidTagType.GetInvocationList()) {
+ TagEventCode code = func(e);
+ switch (code) {
+ case TagEventCode.FAIL:
+ return false;
+ case TagEventCode.PASS:
+ return true;
+ }
+ }
}
+
+ return false;
}
- protected void OnInvalidTagValue (TagEventArgs e)
+ ///
+ /// Processes registered events for whenever an expected has a value that violates the schema.
+ ///
+ /// Arguments for this event.
+ /// Status indicating whether this event can be ignored.
+ protected virtual bool OnInvalidTagValue (TagEventArgs e)
{
if (InvalidTagValue != null) {
- InvalidTagValue(this, e);
+ foreach (Func func in InvalidTagValue.GetInvocationList()) {
+ TagEventCode code = func(e);
+ switch (code) {
+ case TagEventCode.FAIL:
+ return false;
+ case TagEventCode.PASS:
+ return true;
+ }
+ }
}
+
+ return false;
}
#endregion
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNode.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNode.cs
new file mode 100644
index 0000000..e391185
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNode.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A node in an NBT schema definition, used to define what values are considered valid for a given NBT node.
+ ///
+ public abstract class SchemaNode
+ {
+ private string _name;
+ private SchemaOptions _options;
+
+ ///
+ /// Gets the name of an expected NBT node.
+ ///
+ public string Name
+ {
+ get { return _name; }
+ }
+
+ ///
+ /// Gets additional schema options defined for this node.
+ ///
+ public SchemaOptions Options
+ {
+ get { return _options; }
+ }
+
+ ///
+ /// Constructs a new representing a named .
+ ///
+ /// The name of the corresponding .
+ protected SchemaNode (string name)
+ {
+ _name = name;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ protected SchemaNode (string name, SchemaOptions options)
+ {
+ _name = name;
+ _options = options;
+ }
+
+ ///
+ /// Construct a sensible default NBT tree representative of this schema node.
+ ///
+ /// A that is valid for this schema node.
+ public virtual TagNode BuildDefaultTree ()
+ {
+ return null;
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNodeArray.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNodeArray.cs
new file mode 100644
index 0000000..83ae33f
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNodeArray.cs
@@ -0,0 +1,81 @@
+using System;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A concrete representing a .
+ ///
+ public sealed class SchemaNodeArray : SchemaNode
+ {
+ private int _length;
+
+ ///
+ /// Gets the expected length of the corresponding byte array.
+ ///
+ public int Length
+ {
+ get { return _length; }
+ }
+
+ ///
+ /// Indicates whether there is an expected length of the corresponding byte array.
+ ///
+ public bool HasExpectedLength
+ {
+ get { return _length > 0; }
+ }
+
+ ///
+ /// Constructs a new representing a named .
+ ///
+ /// The name of the corresponding .
+ public SchemaNodeArray (string name)
+ : base(name)
+ {
+ _length = 0;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeArray (string name, SchemaOptions options)
+ : base(name, options)
+ {
+ _length = 0;
+ }
+
+ ///
+ /// Constructs a new representing a named with expected length .
+ ///
+ /// The name of the corresponding .
+ /// The expected length of corresponding byte array.
+ public SchemaNodeArray (string name, int length)
+ : base(name)
+ {
+ _length = length;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The expected length of corresponding byte array.
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeArray (string name, int length, SchemaOptions options)
+ : base(name, options)
+ {
+ _length = length;
+ }
+
+ ///
+ /// Constructs a default satisfying the constraints of this node.
+ ///
+ /// A with a sensible default value.
+ public override TagNode BuildDefaultTree ()
+ {
+ return new TagNodeByteArray(new byte[_length]);
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNodeCompound.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNodeCompound.cs
new file mode 100644
index 0000000..91bad22
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNodeCompound.cs
@@ -0,0 +1,219 @@
+using System;
+using System.Collections.Generic;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A concrete representing a .
+ ///
+ public sealed class SchemaNodeCompound : SchemaNode, ICollection
+ {
+ private List _subnodes;
+
+ #region ICollection Members
+
+ ///
+ /// Adds a as a child of this node.
+ ///
+ /// The to add.
+ public void Add (SchemaNode item)
+ {
+ _subnodes.Add(item);
+ }
+
+ ///
+ /// Removes all objects from the node.
+ ///
+ public void Clear ()
+ {
+ _subnodes.Clear();
+ }
+
+ ///
+ /// Checks if a is a child of this node.
+ ///
+ /// The to check for existance.
+ /// Status indicating if the exists as a child of this node.
+ public bool Contains (SchemaNode item)
+ {
+ return _subnodes.Contains(item);
+ }
+
+ ///
+ /// Copies all child objects of this node to a compatible one-dimensional array, starting at the specified index of the target array.
+ ///
+ /// The one-dimensional that is the destination of the subnodes copied. The Array must have zero-based indexing.
+ /// The zero-based index in at which copying begins.
+ public void CopyTo (SchemaNode[] array, int arrayIndex)
+ {
+ _subnodes.CopyTo(array, arrayIndex);
+ }
+
+ ///
+ /// Gets the number of child objects in this node.
+ ///
+ public int Count
+ {
+ get { return _subnodes.Count; }
+ }
+
+ ///
+ /// Gets a value indicating whether the node is readonly.
+ ///
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Removes the first occurance of a from this node.
+ ///
+ /// The to remove.
+ /// Status indicating whether a was removed.
+ public bool Remove (SchemaNode item)
+ {
+ return _subnodes.Remove(item);
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ ///
+ /// Iterates through all of the objects in this .
+ ///
+ /// An enumerator for this node.
+ public IEnumerator GetEnumerator ()
+ {
+ return _subnodes.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ ///
+ /// Iterates through all of the objects in this .
+ ///
+ /// An enumerator for this node.
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
+ {
+ return _subnodes.GetEnumerator();
+ }
+
+ #endregion
+
+ ///
+ /// Constructs a new representing a root .
+ ///
+ public SchemaNodeCompound ()
+ : base("")
+ {
+ _subnodes = new List();
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeCompound (SchemaOptions options)
+ : base("", options)
+ {
+ _subnodes = new List();
+ }
+
+ ///
+ /// Constructs a new representing a named .
+ ///
+ /// The name of the corresponding .
+ public SchemaNodeCompound (string name)
+ : base(name)
+ {
+ _subnodes = new List();
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeCompound (string name, SchemaOptions options)
+ : base(name, options)
+ {
+ _subnodes = new List();
+ }
+
+ ///
+ /// Constructs a new representing a named matching the given schema.
+ ///
+ /// The name of the corresponding .
+ /// A representing a schema to verify against the corresponding .
+ public SchemaNodeCompound (string name, SchemaNode subschema)
+ : base(name)
+ {
+ _subnodes = new List();
+
+ SchemaNodeCompound schema = subschema as SchemaNodeCompound;
+ if (schema == null) {
+ return;
+ }
+
+ foreach (SchemaNode node in schema._subnodes) {
+ _subnodes.Add(node);
+ }
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// A representing a schema to verify against the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeCompound (string name, SchemaNode subschema, SchemaOptions options)
+ : base(name, options)
+ {
+ _subnodes = new List();
+
+ SchemaNodeCompound schema = subschema as SchemaNodeCompound;
+ if (schema == null) {
+ return;
+ }
+
+ foreach (SchemaNode node in schema._subnodes) {
+ _subnodes.Add(node);
+ }
+ }
+
+ ///
+ /// Copies all the elements of this into .
+ ///
+ /// The destination to copy elements into.
+ /// A reference to .
+ public SchemaNodeCompound MergeInto (SchemaNodeCompound tree)
+ {
+ foreach (SchemaNode node in _subnodes) {
+ SchemaNode f = tree._subnodes.Find(n => n.Name == node.Name);
+ if (f != null) {
+ continue;
+ }
+ tree.Add(node);
+ }
+
+ return tree;
+ }
+
+ ///
+ /// Constructs a default satisfying the constraints of this node.
+ ///
+ /// A with a sensible default value. A default child is created for every contained in this .
+ public override TagNode BuildDefaultTree ()
+ {
+ TagNodeCompound list = new TagNodeCompound();
+ foreach (SchemaNode node in _subnodes) {
+ list[node.Name] = node.BuildDefaultTree();
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNodeList.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNodeList.cs
new file mode 100644
index 0000000..a979374
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNodeList.cs
@@ -0,0 +1,172 @@
+using System;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A concrete representing a .
+ ///
+ public sealed class SchemaNodeList : SchemaNode
+ {
+ private TagType _type;
+ private int _length;
+ private SchemaNode _subschema;
+
+ ///
+ /// Gets the expected number of items contained in the corresponding .
+ ///
+ public int Length
+ {
+ get { return _length; }
+ }
+
+ ///
+ /// Gets the expected of the items contained in the corresponding .
+ ///
+ public TagType Type
+ {
+ get { return _type; }
+ }
+
+ ///
+ /// Gets a representing a schema that items contained in the corresponding should be verified against.
+ ///
+ public SchemaNode SubSchema
+ {
+ get { return _subschema; }
+ }
+
+ ///
+ /// Indicates whether there is an expected number of items of the corresponding .
+ ///
+ public bool HasExpectedLength
+ {
+ get { return _length > 0; }
+ }
+
+ ///
+ /// Constructs a new representing a named containing items of type .
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ public SchemaNodeList (string name, TagType type)
+ : base(name)
+ {
+ _type = type;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeList (string name, TagType type, SchemaOptions options)
+ : base(name, options)
+ {
+ _type = type;
+ }
+
+ ///
+ /// Constructs a new representing a named containing items of type .
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// The number of items contained in the corresponding .
+ public SchemaNodeList (string name, TagType type, int length)
+ : base(name)
+ {
+ _type = type;
+ _length = length;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// The number of items contained in the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeList (string name, TagType type, int length, SchemaOptions options)
+ : base(name, options)
+ {
+ _type = type;
+ _length = length;
+ }
+
+ ///
+ /// Constructs a new representing a named containing items of type matching the given schema.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// A representing a schema to verify against items contained in the corresponding .
+ public SchemaNodeList (string name, TagType type, SchemaNode subschema)
+ : base(name)
+ {
+ _type = type;
+ _subschema = subschema;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// A representing a schema to verify against items contained in the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeList (string name, TagType type, SchemaNode subschema, SchemaOptions options)
+ : base(name, options)
+ {
+ _type = type;
+ _subschema = subschema;
+ }
+
+ ///
+ /// Constructs a new representing a named containing items of type matching the given schema.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// The number of items contained in the corresponding .
+ /// A representing a schema to verify against items contained in the corresponding .
+ public SchemaNodeList (string name, TagType type, int length, SchemaNode subschema)
+ : base(name)
+ {
+ _type = type;
+ _length = length;
+ _subschema = subschema;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The type of items contained in the corresponding .
+ /// The number of items contained in the corresponding .
+ /// A representing a schema to verify against items contained in the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeList (string name, TagType type, int length, SchemaNode subschema, SchemaOptions options)
+ : base(name, options)
+ {
+ _type = type;
+ _length = length;
+ _subschema = subschema;
+ }
+
+ ///
+ /// Constructs a default satisfying the constraints of this node.
+ ///
+ /// A with a sensible default value. If a length is specified, default child objects of the necessary type will be created and added to the .
+ public override TagNode BuildDefaultTree ()
+ {
+ if (_length == 0) {
+ return new TagNodeList(_type);
+ }
+
+ TagNodeList list = new TagNodeList(_type);
+ for (int i = 0; i < _length; i++) {
+ list.Add(_subschema.BuildDefaultTree());
+ }
+
+ return list;
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNodeScaler.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNodeScaler.cs
new file mode 100644
index 0000000..7d591a8
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNodeScaler.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A concrete representing a scaler-type .
+ ///
+ public sealed class SchemaNodeScaler : SchemaNode
+ {
+ private TagType _type;
+
+ ///
+ /// Gets the scaler that this node represents.
+ ///
+ public TagType Type
+ {
+ get { return _type; }
+ }
+
+ ///
+ /// Constructs a new representing a named and of type .
+ ///
+ /// The name of the corresponding .
+ /// The type of the corresponding , restricted to scaler types.
+ public SchemaNodeScaler (string name, TagType type)
+ : base(name)
+ {
+ _type = type;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The type of the corresponding , restricted to scaler types.
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeScaler (string name, TagType type, SchemaOptions options)
+ : base(name, options)
+ {
+ _type = type;
+ }
+
+ ///
+ /// Constructs a default according to the this node represents.
+ ///
+ /// A with a sensible default value.
+ public override TagNode BuildDefaultTree ()
+ {
+ switch (_type) {
+ case TagType.TAG_STRING:
+ return new TagNodeString();
+
+ case TagType.TAG_BYTE:
+ return new TagNodeByte();
+
+ case TagType.TAG_SHORT:
+ return new TagNodeShort();
+
+ case TagType.TAG_INT:
+ return new TagNodeInt();
+
+ case TagType.TAG_LONG:
+ return new TagNodeLong();
+
+ case TagType.TAG_FLOAT:
+ return new TagNodeFloat();
+
+ case TagType.TAG_DOUBLE:
+ return new TagNodeDouble();
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaNodeString.cs b/Substrate/SubstrateCS/Source/NBT/SchemaNodeString.cs
new file mode 100644
index 0000000..fa5505b
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaNodeString.cs
@@ -0,0 +1,116 @@
+using System;
+
+namespace Substrate.NBT
+{
+ ///
+ /// A concrete representing a .
+ ///
+ public sealed class SchemaNodeString : SchemaNode
+ {
+ private string _value = "";
+ private int _length;
+
+ ///
+ /// Gets the maximum length of a valid string.
+ ///
+ public int Length
+ {
+ get { return _length; }
+ }
+
+ ///
+ /// Gets the expected value of a valid string.
+ ///
+ /// A must be set to this value to be considered valid.
+ public string Value
+ {
+ get { return _value; }
+ }
+
+ ///
+ /// Indicates whether there is a maximum-length constraint on strings in this node.
+ ///
+ public bool HasMaxLength
+ {
+ get { return _length > 0; }
+ }
+
+ ///
+ /// Constructs a new representing a named .
+ ///
+ /// The name of the corresponding .
+ public SchemaNodeString (string name)
+ : base(name)
+ {
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeString (string name, SchemaOptions options)
+ : base(name, options)
+ {
+ }
+
+ ///
+ /// Constructs a new representing a named set to .
+ ///
+ /// The name of the corresponding .
+ /// The value that the corresponding must be set to.
+ public SchemaNodeString (string name, string value)
+ : base(name)
+ {
+ _value = value;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The value that the corresponding must be set to.
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeString (string name, string value, SchemaOptions options)
+ : base(name, options)
+ {
+ _value = value;
+ }
+
+ ///
+ /// Constructs a new representing a named with maximum length .
+ ///
+ /// The name of the corresponding .
+ /// The maximum length of strings in the corresponding .
+ public SchemaNodeString (string name, int length)
+ : base(name)
+ {
+ _length = length;
+ }
+
+ ///
+ /// Constructs a new with additional options.
+ ///
+ /// The name of the corresponding .
+ /// The maximum length of strings in the corresponding .
+ /// One or more option flags modifying the processing of this node.
+ public SchemaNodeString (string name, int length, SchemaOptions options)
+ : base(name, options)
+ {
+ _length = length;
+ }
+
+ ///
+ /// Constructs a default satisfying the constraints of this node.
+ ///
+ /// A with a sensible default value. If this node represents a particular string, the constructed will be set to that string.
+ public override TagNode BuildDefaultTree ()
+ {
+ if (_value.Length > 0) {
+ return new TagNodeString(_value);
+ }
+
+ return new TagNodeString();
+ }
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/SchemaOptions.cs b/Substrate/SubstrateCS/Source/NBT/SchemaOptions.cs
new file mode 100644
index 0000000..a0d0114
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/SchemaOptions.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Substrate.NBT
+{
+ ///
+ /// Additional options that modify the processing of a .
+ ///
+ [Flags]
+ public enum SchemaOptions
+ {
+ ///
+ /// Any with this option will not throw an error if the corresponding is missing.
+ ///
+ OPTIONAL = 0x1,
+
+ ///
+ /// If a cannot be found for a marked with this option, a sensible default will be created and inserted into the tree.
+ ///
+ CREATE_ON_MISSING = 0x2,
+ }
+}
diff --git a/Substrate/SubstrateCS/Source/NBT/TagNodeDouble.cs b/Substrate/SubstrateCS/Source/NBT/TagNodeDouble.cs
index 03bbda7..3b7e92d 100644
--- a/Substrate/SubstrateCS/Source/NBT/TagNodeDouble.cs
+++ b/Substrate/SubstrateCS/Source/NBT/TagNodeDouble.cs
@@ -81,7 +81,7 @@ namespace Substrate.NBT
///
/// Converts a system double to a double node representing the same value.
///
- /// A double value.
+ /// A double value.
/// A new double node containing the given value.
public static implicit operator TagNodeDouble (double d)
{
diff --git a/Substrate/SubstrateCS/Source/NBT/TagNodeString.cs b/Substrate/SubstrateCS/Source/NBT/TagNodeString.cs
index f1df7bb..c973863 100644
--- a/Substrate/SubstrateCS/Source/NBT/TagNodeString.cs
+++ b/Substrate/SubstrateCS/Source/NBT/TagNodeString.cs
@@ -89,7 +89,7 @@ namespace Substrate.NBT
///
/// Converts a string node to a system string representing the same data.
///
- /// A string node.
+ /// A string node.
/// A system string set to the node's data.
public static implicit operator string (TagNodeString s)
{
diff --git a/Substrate/SubstrateCS/Source/NBT/VerifierLogger.cs b/Substrate/SubstrateCS/Source/NBT/VerifierLogger.cs
new file mode 100644
index 0000000..a44873e
--- /dev/null
+++ b/Substrate/SubstrateCS/Source/NBT/VerifierLogger.cs
@@ -0,0 +1,48 @@
+using System;
+
+namespace Substrate.NBT
+{
+ using Substrate.Utility;
+
+ ///
+ /// A collection of static methods that can be hooked into events for logging NBT errors to the console.
+ ///
+ public static class VerifierLogger
+ {
+ ///
+ /// Logs an occurance of a missing tag error, and advances to the next event in the event chain.
+ ///
+ /// Data about the NBT node being verified.
+ /// A indicating whether event processing should pass, fail, or advance.
+ public static TagEventCode MissingTagHandler (TagEventArgs e)
+ {
+ Console.WriteLine("Missing Tag Error: '{0}'", e.TagName);
+
+ return TagEventCode.NEXT;
+ }
+
+ ///
+ /// Logs an occurance of an invalid tag type error, and advances to the next event in the event chain.
+ ///
+ /// Data about the NBT node being verified.
+ /// A indicating whether event processing should pass, fail, or advance.
+ public static TagEventCode InvalidTagTypeHandler (TagEventArgs e)
+ {
+ Console.WriteLine("Invalid Tag Type Error: '{0}' has type '{1}', expected '{2}'", e.TagName, e.Tag.GetTagType(), e.Schema.ToString());
+
+ return TagEventCode.NEXT;
+ }
+
+ ///
+ /// Logs an occurance of an invalid tag value error, and advances to the next event in the event chain.
+ ///
+ /// Data about the NBT node being verified.
+ /// A indicating whether event processing should pass, fail, or advance.
+ public static TagEventCode InvalidTagValueHandler (TagEventArgs e)
+ {
+ Console.WriteLine("Invalid Tag Value Error: '{0}' of type '{1}' is set to invalid value '{2}'", e.TagName, e.Tag.GetTagType(), e.Tag.ToString());
+
+ return TagEventCode.NEXT;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Substrate/SubstrateCS/Substrate.csproj b/Substrate/SubstrateCS/Substrate.csproj
index f835b24..3d941cf 100644
--- a/Substrate/SubstrateCS/Substrate.csproj
+++ b/Substrate/SubstrateCS/Substrate.csproj
@@ -60,10 +60,6 @@
Assemblies\Ionic.Zlib.dll
-
-
-
-
@@ -76,6 +72,14 @@
+
+
+
+
+
+
+
+
@@ -89,6 +93,7 @@
+
@@ -138,7 +143,6 @@
-
@@ -156,6 +160,7 @@
+