/// <summary>
        ///     Fills an event signature object from an XML fragment.
        /// </summary>
        /// <param name="reader">The XML reader containing the fragment to read.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="reader" /> is <c>null</c>.</exception>
        /// <exception cref="LSLLibraryDataXmlSyntaxException">
        ///     On missing or unknown attributes.
        ///     If a parameter 'Name' is used more than once.
        ///     If a parameter 'Name' is whitespace.
        ///     If a parameter 'Type' is <see cref="LSLType.Void" />.
        ///     If a parameter 'Type' does not correspond to an <see cref="LSLType" /> enumeration member.
        ///     If a 'Properties' node 'Name' is <c>null</c> or whitespace.
        ///     If a 'Properties' node 'Name' is used more than once.
        ///     If a 'Properties' node 'Value' is <c>null</c> or whitespace.
        /// </exception>
        /// <exception cref="LSLInvalidSymbolNameException">
        ///     Thrown if the event signatures name or any of its parameters names do
        ///     not abide by LSL symbol naming conventions.
        /// </exception>
        /// <exception cref="XmlException">Incorrect XML encountered in the input stream. </exception>
        /// <exception cref="LSLInvalidSubsetNameException">
        ///     Thrown if any of the given subset names in the 'Subsets' CSV string do
        ///     not match the pattern ([a-zA-Z]+[a-zA-Z_0-9\\-]*).
        /// </exception>
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            var parameterNames = new HashSet <string>();


            reader.MoveToContent();

            var hasSubsets = false;
            var hasName    = false;

            var lineNumberInfo = (IXmlLineInfo)reader;

            while (reader.MoveToNextAttribute())
            {
                if (reader.Name == "Subsets")
                {
                    Subsets.SetSubsets(reader.Value);
                    hasSubsets = true;
                }
                else if (reader.Name == "Name")
                {
                    hasName = true;
                    Name    = reader.Value;
                }
                else
                {
                    throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                               string.Format("EventHandler{0}: Unknown attribute '{1}'.",
                                                                             hasName ? (" '" + Name + "'") : "", reader.Name));
                }
            }


            if (!hasName)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           "EventHandler: Missing Name attribute.");
            }


            if (!hasSubsets)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("EventHandler '{0}': Missing Subsets attribute.", Name));
            }


            var canRead = reader.Read();

            while (canRead)
            {
                if ((reader.Name == "Parameter") && reader.IsStartElement())
                {
                    var pName = reader.GetAttribute("Name");
                    if (string.IsNullOrWhiteSpace(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "EventHandler '{0}': Parameter Name attribute invalid, cannot be empty or whitespace.",
                                                                       Name));
                    }

                    LSLType pType;

                    if (!Enum.TryParse(reader.GetAttribute("Type"), out pType))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("EventHandler '{0}': Parameter named '{1}' has an invalid Type attribute.",
                                                                                 pName, Name));
                    }

                    if (pType == LSLType.Void)
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "EventHandler '{0}': Parameter named '{1}' has an invalid Type, event parameters cannot be Void.",
                                                                       Name, pName));
                    }

                    if (parameterNames.Contains(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("EventHandler '{0}': Parameter Name '{1}' already used.", Name, pName));
                    }

                    parameterNames.Add(pName);
                    AddParameter(new LSLParameterSignature(pType, pName, false));

                    canRead = reader.Read();
                }
                else if ((reader.Name == "DocumentationString") && reader.IsStartElement())
                {
                    DocumentationString = reader.ReadElementContentAsString();
                    canRead             = reader.Read();
                }
                else if ((reader.Name == "Property") && reader.IsStartElement())
                {
                    var pName = reader.GetAttribute("Name");

                    if (string.IsNullOrWhiteSpace(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("EventHandler '{0}': Property element's Name attribute cannot be empty.",
                                                                                 pName));
                    }

                    var value = reader.GetAttribute("Value");

                    if (string.IsNullOrWhiteSpace(value))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("EventHandler '{0}': Property element's Value attribute cannot be empty.",
                                                                                 pName));
                    }

                    if (_properties.ContainsKey(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "EventHandler '{0}': Property name '{1}' has already been used.", Name, pName));
                    }

                    _properties.Add(pName, value);

                    canRead = reader.Read();
                }
                else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "EventHandler")
                {
                    break;
                }
                else
                {
                    canRead = reader.Read();
                }
            }
        }
        /// <summary>
        ///     Fills a constant signature object from an XML fragment.
        /// </summary>
        /// <param name="reader">The XML reader containing the fragment to read.</param>
        /// <exception cref="LSLInvalidSymbolNameException">
        ///     Thrown if the constants name does not abide by LSL symbol naming
        ///     conventions.
        /// </exception>
        /// <exception cref="LSLInvalidSubsetNameException">
        ///     Thrown if any of the given subset names in the CSV 'Subsets' string do
        ///     not match the pattern ([a-zA-Z]+[a-zA-Z_0-9\\-]*).
        /// </exception>
        /// <exception cref="LSLInvalidConstantTypeException">if 'Type' is <see cref="LSLType.Void" />.</exception>
        /// <exception cref="LSLLibraryDataXmlSyntaxException">
        ///     On missing or unknown attributes.
        ///     If the constant 'Type' is <see cref="LSLType.Void" />.
        ///     If the constant 'Type' does not correspond to an <see cref="LSLType" /> enumeration member.
        ///     If a 'Properties' node 'Name' is <c>null</c> or whitespace.
        ///     If a 'Properties' node 'Name' is used more than once.
        ///     If a 'Properties' node 'Value' is <c>null</c> or whitespace.
        /// </exception>
        /// <exception cref="LSLInvalidConstantValueStringException">
        ///     If 'Value' is an invalid value for a float and <see cref="LSLConstantSignature.Type" /> is set to <see cref="LSLType.Float" />
        ///     or
        ///     If 'Value' is an invalid value for an integer and <see cref="LSLConstantSignature.Type" /> is set to <see cref="LSLType.Integer" />
        ///     or
        ///     If 'Value' is an invalid value for a vector and <see cref="LSLConstantSignature.Type" /> is set to <see cref="LSLType.Vector" />
        ///     or
        ///     If 'Value' is an invalid value for a rotation and <see cref="LSLConstantSignature.Type" /> is set to <see cref="LSLType.Rotation" />
        /// </exception>
        /// <exception cref="XmlException">Incorrect XML encountered in the input stream. </exception>
        /// <exception cref="ArgumentNullException"><paramref name="reader" /> is <c>null</c>.</exception>
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            reader.MoveToContent();

            var hasSubsets = false;
            var hasType    = false;
            var hasName    = false;
            var hasValue   = false;

            string valueString = null;

            var lineNumberInfo = (IXmlLineInfo)reader;

            while (reader.MoveToNextAttribute())
            {
                if (reader.Name == "Value")
                {
                    var val = reader.Value;
                    //The value is only truly missing if its entirely devoid of character data
                    //some LSL constants like EOF are nothing but whitespace characters
                    if (val.Length != 0)
                    {
                        hasValue = true;
                    }

                    //need to set the type first, defer this until later.
                    valueString = val;
                }
                else if (reader.Name == "Subsets")
                {
                    Subsets.SetSubsets(reader.Value);
                    hasSubsets = true;
                }
                else if (reader.Name == "Type")
                {
                    LSLType type;
                    if (Enum.TryParse(reader.Value, out type))
                    {
                        Type    = type;
                        hasType = true;
                    }
                    else
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryConstantSignature{0}: Type attribute invalid.",
                                                                                 hasName ? (" '" + Name + "'") : ""));
                    }
                }
                else if (reader.Name == "Name")
                {
                    Name    = reader.Value;
                    hasName = true;
                }
                else
                {
                    throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                               string.Format("LibraryConstantSignature{0}: Unknown attribute '{1}'.",
                                                                             hasName ? (" '" + Name + "'") : "", reader.Name));
                }
            }

            if (!hasName)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           "LibraryConstantSignature: Missing Name attribute.");
            }

            if (!hasType)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("LibraryConstantSignature '{0}': Missing Type attribute.", Name));
            }

            if (!hasValue)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("LibraryConstantSignature '{0}': Missing Value attribute.", Name));
            }

            if (!hasSubsets)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("LibraryConstantSignature '{0}': Missing Subsets attribute.", Name));
            }

            //Set the value string, this can possibly throw an LSLInvalidConstantValueStringException
            //The Type property needs to be set first above for validation to occur.
            ValueString = valueString;


            var canRead = reader.Read();

            while (canRead)
            {
                if ((reader.Name == "DocumentationString") && reader.IsStartElement())
                {
                    DocumentationString = reader.ReadElementContentAsString();
                    canRead             = reader.Read();
                }
                else if ((reader.Name == "Property") && reader.IsStartElement())
                {
                    var pName = reader.GetAttribute("Name");

                    if (string.IsNullOrWhiteSpace(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryConstantSignature '{0}': Property element's Name attribute cannot be empty.",
                                                                       Name));
                    }

                    var value = reader.GetAttribute("Value");

                    if (string.IsNullOrWhiteSpace(value))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryConstantSignature '{0}': Property element's Value attribute cannot be empty.",
                                                                       Name));
                    }

                    if (_properties.ContainsKey(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryConstantSignature '{0}': Property name '{1}' has already been used.", Name,
                                                                       pName));
                    }

                    _properties.Add(pName, value);

                    canRead = reader.Read();
                }
                else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "LibraryConstant")
                {
                    break;
                }
                else
                {
                    canRead = reader.Read();
                }
            }
        }
示例#3
0
        /// <summary>
        ///     Fills a function signature object from an XML fragment.
        /// </summary>
        /// <param name="reader">The XML reader containing the fragment to read.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="reader" /> is <c>null</c>.</exception>
        /// <exception cref="LSLLibraryDataXmlSyntaxException">
        ///     On missing or unknown attributes.
        ///     If a parameter 'Name' is used more than once.
        ///     If a parameter 'Name' is whitespace.
        ///     If a parameter 'Type' is <see cref="LSLType.Void" /> and not Variadic.
        ///     If a parameter 'Type' does not correspond to an <see cref="LSLType" /> enumeration member.
        ///     If a 'Properties' node 'Name' is <c>null</c> or whitespace.
        ///     If a 'Properties' node 'Name' is used more than once.
        ///     If a 'Properties' node 'Value' is <c>null</c> or whitespace.
        /// </exception>
        /// <exception cref="LSLInvalidSymbolNameException">
        ///     Thrown if the function signatures name or any of its parameters names
        ///     do not abide by LSL symbol naming conventions.
        /// </exception>
        /// <exception cref="XmlException">Incorrect XML encountered in the input stream. </exception>
        /// <exception cref="LSLInvalidSubsetNameException">
        ///     Thrown if any of the given subset names in the 'Subsets' CSV string do
        ///     not match the pattern ([a-zA-Z]+[a-zA-Z_0-9\\-]*).
        /// </exception>
        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }


            var parameterNames = new HashSet <string>();

            var lineNumberInfo = (IXmlLineInfo)reader;

            reader.MoveToContent();
            var hasReturnType = false;
            var hasSubsets    = false;
            var hasName       = false;

            while (reader.MoveToNextAttribute())
            {
                if (reader.Name == "Subsets")
                {
                    Subsets.SetSubsets(reader.Value);
                    hasSubsets = true;
                }
                else if (reader.Name == "ReturnType")
                {
                    LSLType type;
                    if (Enum.TryParse(reader.Value, out type))
                    {
                        ReturnType    = type;
                        hasReturnType = true;
                    }
                    else
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction{0}: ReturnType attribute Value '{1}' invalid.",
                                                                                 hasName ? (" '" + Name + "'") : "", reader.Value));
                    }
                }
                else if (reader.Name == "Name")
                {
                    hasName = true;
                    Name    = reader.Value;
                }
                else
                {
                    throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                               string.Format("LibraryFunction{0}: Unknown attribute '{1}'.",
                                                                             hasName ? (" '" + Name + "'") : "", reader.Name));
                }
            }


            if (!hasName)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           "LibraryFunction: Missing Name attribute.");
            }

            if (!hasReturnType)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("LibraryFunction '{0}': Missing ReturnType attribute.", Name));
            }

            if (!hasSubsets)
            {
                throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                           string.Format("LibraryFunction '{0}': Missing Subsets attribute.", Name));
            }

            var isVariadic = false;

            var canRead = reader.Read();

            while (canRead)
            {
                if ((reader.Name == "Parameter") && reader.IsStartElement())
                {
                    if (isVariadic)
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction '{0}': More than one variadic parameter was defined.", Name));
                    }

                    var pName = reader.GetAttribute("Name");

                    if (string.IsNullOrWhiteSpace(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryFunction '{0}': Parameter Name attribute invalid, cannot be empty or whitespace.",
                                                                       Name));
                    }

                    LSLType pType;

                    if (!Enum.TryParse(reader.GetAttribute("Type"), out pType))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryFunction '{0}': Parameter named '{1}' has an invalid Type attribute.", Name,
                                                                       pName));
                    }

                    if (parameterNames.Contains(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction '{0}': Parameter Name '{1}' already used.", Name, pName));
                    }

                    var variadic = reader.GetAttribute("Variadic");


                    if (!string.IsNullOrWhiteSpace(variadic))
                    {
                        if (variadic.ToLower() == "true")
                        {
                            isVariadic = true;
                        }
                        else if (variadic.ToLower() != "false")
                        {
                            throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                       string.Format(
                                                                           "LibraryFunction '{0}': Variadic attribute in parameter #{1} of Function '{2}' must equal True or False (Case Insensitive).",
                                                                           Name, pName, Name));
                        }
                    }

                    if (pType == LSLType.Void && !isVariadic)
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format(
                                                                       "LibraryFunction '{0}': Parameter Type invalid, function parameters cannot be Void unless they are declared variadic.",
                                                                       Name));
                    }

                    parameterNames.Add(pName);
                    AddParameter(new LSLParameterSignature(pType, pName, isVariadic));

                    canRead = reader.Read();
                }
                else if ((reader.Name == "DocumentationString") && reader.IsStartElement())
                {
                    DocumentationString = reader.ReadElementContentAsString();
                    canRead             = reader.Read();
                }
                else if ((reader.Name == "Property") && reader.IsStartElement())
                {
                    var pName = reader.GetAttribute("Name");

                    if (string.IsNullOrWhiteSpace(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction '{0}': Property element's Name attribute cannot be empty.",
                                                                                 Name));
                    }

                    var value = reader.GetAttribute("Value");

                    if (string.IsNullOrWhiteSpace(value))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction '{0}': Property element's Value attribute cannot be empty.",
                                                                                 Name));
                    }

                    if (_properties.ContainsKey(pName))
                    {
                        throw new LSLLibraryDataXmlSyntaxException(lineNumberInfo.LineNumber,
                                                                   string.Format("LibraryFunction '{0}': Property name '{1}' has already been used.", Name,
                                                                                 pName));
                    }

                    _properties.Add(pName, value);

                    canRead = reader.Read();
                }
                else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "LibraryFunction")
                {
                    break;
                }
                else
                {
                    canRead = reader.Read();
                }
            }
        }