Beispiel #1
0
        // XPath spec $4.2, string()
        public QilNode ConvertToString(QilNode n)
        {
            switch (n.XmlType.TypeCode)
            {
            case XmlTypeCode.Boolean:
                return(
                    n.NodeType == QilNodeType.True  ? (QilNode)String("true") :
                    n.NodeType == QilNodeType.False ? (QilNode)String("false") :
                    /*default: */ (QilNode)Conditional(n, String("true"), String("false"))
                    );

            case XmlTypeCode.Double:
                return(n.NodeType == QilNodeType.LiteralDouble
                    ? (QilNode)String(XPathConvert.DoubleToString((double)(QilLiteral)n))
                    : (QilNode)XsltConvert(n, T.StringX)
                       );

            case XmlTypeCode.String:
                return(n);

            default:
                if (n.XmlType.IsNode)
                {
                    return(XPathNodeValue(SafeDocOrderDistinct(n)));
                }

                ExpectAny(n);
                return(XsltConvert(n, T.StringX));
            }
        }
        private void ScanNumber()
        {
            Debug.Assert(xmlCharType.IsDigit(curChar));
            int start = curIndex;

            while (xmlCharType.IsDigit(curChar))
            {
                NextChar();
            }
            if (curChar == '.')
            {
                NextChar();
                while (xmlCharType.IsDigit(curChar))
                {
                    NextChar();
                }
            }
            if ((curChar & (~0x20)) == 'E')
            {
                NextChar();
                if (curChar == '+' || curChar == '-')
                {
                    NextChar();
                }
                while (xmlCharType.IsDigit(curChar))
                {
                    NextChar();
                }
                throw CreateException(Res.XPath_ScientificNotation);
            }
            this.kind        = LexKind.Number;
            this.numberValue = XPathConvert.StringToDouble(xpathExpr.Substring(start, curIndex - start));
        }
Beispiel #3
0
        public static double ToDouble(XPathItem item)
        {
            XsltLibrary.CheckXsltValue(item);

            if (item.IsNode)
            {
                return(XPathConvert.StringToDouble(item.Value));
            }

            Type itemType = item.ValueType;

            if (itemType == StringType)
            {
                return(XPathConvert.StringToDouble(item.Value));
            }
            else if (itemType == DoubleType)
            {
                return(item.ValueAsDouble);
            }
            else
            {
                Debug.Assert(itemType == BooleanType, $"Unexpected type of atomic sequence {itemType}");
                return(item.ValueAsBoolean ? 1d : 0d);
            }
        }
        public void SetVersion(string version, string attName)
        {
            double versionNum = XPathConvert.StringToDouble(version);

            if (double.IsNaN(versionNum))
            {
                ReportError(/*[XT0110]*/ Res.Xslt_InvalidAttrValue, attName, version);
                versionNum = 1.0;
            }
            scopeManager.ForwardCompatibility = (versionNum != 1.0);
        }
Beispiel #5
0
        public static string ToString(XPathItem item)
        {
            XsltLibrary.CheckXsltValue(item);

            // Use XPath 1.0 rules to convert double to string
            if (!item.IsNode && item.ValueType == DoubleType)
            {
                return(XPathConvert.DoubleToString(item.ValueAsDouble));
            }

            return(item.Value);
        }
        private void ScanFraction()
        {
            Debug.Assert(xmlCharType.IsDigit(curChar));
            int start = curIndex - 1;

            Debug.Assert(0 <= start && xpathExpr[start] == '.');
            while (xmlCharType.IsDigit(curChar))
            {
                NextChar();
            }
            this.kind        = LexKind.Number;
            this.numberValue = XPathConvert.StringToDouble(xpathExpr.Substring(start, curIndex - start));
        }
Beispiel #7
0
        private void SetVersion(int attVersion)
        {
            MoveToLiteralAttribute(attVersion);
            Debug.Assert(IsKeyword(_atoms.Version));
            double version = XPathConvert.StringToDouble(Value);

            if (double.IsNaN(version))
            {
                ReportError(/*[XT0110]*/ SR.Xslt_InvalidAttrValue, _atoms.Version, Value);
#if XSLT2
                version = 2.0;
#else
                version = 1.0;
#endif
            }
            SetVersion(version);
        }
Beispiel #8
0
        /*
         *   PrimaryExpr ::= Literal | Number | VariableReference | '(' Expr ')' | FunctionCall
         */
        private Node ParsePrimaryExpr()
        {
            Debug.Assert(IsPrimaryExpr());
            Node opnd;

            switch (scanner.Kind)
            {
            case LexKind.String:
                opnd = builder.String(scanner.StringValue);
                scanner.NextLex();
                break;

            case LexKind.Number:
                opnd = builder.Number(XPathConvert.StringToDouble(scanner.RawValue));
                scanner.NextLex();
                break;

            case LexKind.Dollar:
                int startChar = scanner.LexStart;
                scanner.NextLex();
                scanner.CheckToken(LexKind.Name);
                PushPosInfo(startChar, scanner.LexStart + scanner.LexSize);
                opnd = builder.Variable(scanner.Prefix, scanner.Name);
                PopPosInfo();
                scanner.NextLex();
                break;

            case LexKind.LParens:
                scanner.NextLex();
                opnd = ParseExpr();
                scanner.PassToken(LexKind.RParens);
                break;

            default:
                Debug.Assert(
                    scanner.Kind == LexKind.Name && scanner.CanBeFunction && !IsNodeType(scanner),
                    "IsPrimaryExpr() returned true, but the lexeme is not recognized"
                    );
                opnd = ParseFunctionCall();
                break;
            }
            return(opnd);
        }
        private static string ConvertToDecimal(double val, int minLen, char zero, string groupSeparator, int groupSize)
        {
            Debug.Assert(val >= 0 && val == Math.Round(val), "ConvertToArabic operates on non-negative integer numbers only");
            string str   = XPathConvert.DoubleToString(val);
            int    shift = zero - '0';

            // Figure out new string length without separators
            int oldLen = str.Length;
            int newLen = Math.Max(oldLen, minLen);

            // Calculate length of string with separators
            if (groupSize != 0)
            {
                Debug.Assert(groupSeparator.Length == 1);
                checked { newLen += (newLen - 1) / groupSize; }
            }

            // If the new number of characters equals the old one, no changes need to be made
            if (newLen == oldLen && shift == 0)
            {
                return(str);
            }

            // If grouping is not needed, add zero padding only
            if (groupSize == 0 && shift == 0)
            {
                return(str.PadLeft(newLen, zero));
            }

            // Add both grouping separators and zero padding to the string representation of a number
#if true
            unsafe
            {
                char *result    = stackalloc char[newLen];
                char  separator = (groupSeparator.Length > 0) ? groupSeparator[0] : ' ';

                fixed(char *pin = str)
                {
                    char *pOldEnd = pin + oldLen - 1;
                    char *pNewEnd = result + newLen - 1;
                    int   cnt     = groupSize;

                    while (true)
                    {
                        // Move digit to its new location (zero if we've run out of digits)
                        *pNewEnd-- = (pOldEnd >= pin) ? (char)(*pOldEnd-- + shift) : zero;
                        if (pNewEnd < result)
                        {
                            break;
                        }
                        if (/*groupSize > 0 && */ --cnt == 0)
                        {
                            // Every groupSize digits insert the separator
                            *pNewEnd-- = separator;
                            cnt = groupSize;
                            Debug.Assert(pNewEnd >= result, "Separator cannot be the first character");
                        }
                    }
                }

                return(new string(result, 0, newLen));
            }
#else
            // Safe version is about 20% slower after NGEN
            char[] result    = new char[newLen];
            char   separator = (groupSeparator.Length > 0) ? groupSeparator[0] : ' ';

            int oldEnd = oldLen - 1;
            int newEnd = newLen - 1;
            int cnt    = groupSize;

            while (true)
            {
                // Move digit to its new location (zero if we've run out of digits)
                result[newEnd--] = (oldEnd >= 0) ? (char)(str[oldEnd--] + shift) : zero;
                if (newEnd < 0)
                {
                    break;
                }
                if (/*groupSize > 0 && */ --cnt == 0)
                {
                    // Every groupSize digits insert the separator
                    result[newEnd--] = separator;
                    cnt = groupSize;
                    Debug.Assert(newEnd >= 0, "Separator cannot be the first character");
                }
            }
            return(new string(result, 0, newLen));
#endif
        }
        /// <summary>
        /// Format the given xsl:number place marker
        /// </summary>
        /// <param name="val">Place marker - either a sequence of ints, or a double singleton</param>
        /// <returns>Formatted string</returns>
        public string FormatSequence(IList <XPathItem> val)
        {
            StringBuilder sb = new StringBuilder();

            // If the value was supplied directly, in the 'value' attribute, check its validity
            if (val.Count == 1 && val[0].ValueType == typeof(double))
            {
                double dblVal = val[0].ValueAsDouble;
                if (!(0.5 <= dblVal && dblVal < double.PositiveInfinity))
                {
                    // Errata E24: It is an error if the number is NaN, infinite or less than 0.5; an XSLT processor may signal
                    // the error; if it does not signal the error, it must recover by converting the number to a string as if
                    // by a call to the 'string' function and inserting the resulting string into the result tree.
                    return(XPathConvert.DoubleToString(dblVal));
                }
            }

            if (_tokens == null)
            {
                // Special case of the default format
                for (int idx = 0; idx < val.Count; idx++)
                {
                    if (idx > 0)
                    {
                        sb.Append('.');
                    }
                    FormatItem(sb, val[idx], DefaultStartChar, 1);
                }
            }
            else
            {
                int       cFormats = _tokens.Count;
                TokenInfo prefix = _tokens[0], suffix;

                if (cFormats % 2 == 0)
                {
                    suffix = null;
                }
                else
                {
                    suffix = _tokens[--cFormats];
                }

                TokenInfo periodicSeparator = 2 < cFormats ? _tokens[cFormats - 2] : s_defaultSeparator;
                TokenInfo periodicFormat    = 0 < cFormats ? _tokens[cFormats - 1] : s_defaultFormat;

                if (prefix != null)
                {
                    prefix.AssertSeparator(true);
                    sb.Append(prefix.formatString, prefix.startIdx, prefix.length);
                }

                int valCount = val.Count;
                for (int i = 0; i < valCount; i++)
                {
                    int  formatIndex = i * 2;
                    bool haveFormat  = formatIndex < cFormats;

                    if (i > 0)
                    {
                        TokenInfo thisSeparator = haveFormat ? _tokens[formatIndex + 0] : periodicSeparator;
                        thisSeparator.AssertSeparator(true);
                        sb.Append(thisSeparator.formatString, thisSeparator.startIdx, thisSeparator.length);
                    }

                    TokenInfo thisFormat = haveFormat ? _tokens[formatIndex + 1] : periodicFormat;
                    thisFormat.AssertSeparator(false);
                    FormatItem(sb, val[i], thisFormat.startChar, thisFormat.length);
                }

                if (suffix != null)
                {
                    suffix.AssertSeparator(true);
                    sb.Append(suffix.formatString, suffix.startIdx, suffix.length);
                }
            }
            return(sb.ToString());
        }
Beispiel #11
0
        //------------------------------------------------------------------------
        // ToString (internal type to internal type)
        //------------------------------------------------------------------------

        public static string ToString(double value)
        {
            return(XPathConvert.DoubleToString(value));
        }
Beispiel #12
0
        //------------------------------------------------------------------------
        // ToDouble (internal type to internal type)
        //------------------------------------------------------------------------

        public static double ToDouble(string value)
        {
            return(XPathConvert.StringToDouble(value));
        }