예제 #1
0
        /// <summary>
        /// Compiles a list of positions and data to insert at said positions in order to make <paramref name="OldData"/> match <paramref name="NewData"/>
        /// </summary>
        /// <returns></returns>
        public LinkedList<DiffData<T>> Compile_Transformations(DataConsumer<T> OldData, DataConsumer<T> NewData, out int outChange)
        {
            if (OldData is null) throw new ArgumentNullException(nameof(OldData));
            if (NewData is null) throw new ArgumentNullException(nameof(NewData));
            Contract.EndContractBlock();

            /* Get all of the places where we have changed */
            LinkedList<DiffNode<T>> Diffs = Get_Difference(OldData, NewData);

            /* We want a series of commands that ONLY replace text which has changed BUT which does not skip CSI commands that may apply to those differences AND which do not include redundant CSI commands */
            int Balance = 0;// Tracks the total balance of data added vs removed
            var RetList = new LinkedList<DiffData<T>>();
            LinkedListNode<DiffNode<T>> node = Diffs.First;

            while (node != null)
            {
                DiffNode<T> current = node.Value;
                /* In order to account for the total changes which have occured we need to ensure that any data which will be overwritten which isn't supposed to be replaced will correctly be updated after overwriting */
                switch (current.Type)
                {
                    case EDiffAction.Modify:
                        {
                            /* This data was already present, it should be invisible to our change count */
                            RetList.AddLast(new DiffData<T>(EDiffAction.Modify, current.StartOffset, NewData.AsMemory().Slice(current.StartOffset, current.Length)));
                        }
                        break;
                    case EDiffAction.Insertion:
                        {/* In the case of inserted data we should insert all the data that WAS at the start of this diff and before the next */

                            RetList.AddLast(new DiffData<T>(EDiffAction.None, current.StartOffset, NewData.AsMemory().Slice(current.StartOffset, current.Length)));
                            Balance += current.Length;
                            var next = node.Next;
                            if (next is object)
                            {
                                /* The length of data we need to repeat is whatever was between our insertion pos and the start of the next diff */
                                var repeat_length = next.Value.StartOffset - current.StartOffset;
                                /* This data was already present, it should be invisible to our change count */
                                RetList.AddLast(new DiffData<T>(EDiffAction.Insertion, current.EndOffset, NewData.AsMemory().Slice(current.EndOffset, repeat_length)));/* We read from this diff's end because in the new buffer the repeated text is after this diff */
                            }
                            else/* No next, insert all needed data */
                            {
                                var repeat_length = (OldData?.Length ?? 0) - current.StartOffset;
                                RetList.AddLast(new DiffData<T>(EDiffAction.Insertion, current.EndOffset, NewData.AsMemory().Slice(current.EndOffset, repeat_length)));/* We read from this diff's end because in the new buffer the repeated text is after this diff */
                            }
                        }
                        break;
                    case EDiffAction.Removal:
                        {/* For removals we just want to track how much data was removed */
                            Balance -= current.Length;
                        }
                        break;
                }

                node = node.Next;
            }

            outChange = Balance;
            return RetList;
        }
예제 #2
0
        public static void Consume_Number(DataConsumer <char> Stream, out ReadOnlyMemory <char> /*  */ outResult, out object outNumber, out ENumericTokenType outType)
        {/* Docs: https://www.w3.org/TR/css-syntax-3/#consume-number */
            if (Stream is null)
            {
                throw new ArgumentNullException(nameof(Stream));
            }
            Contract.EndContractBlock();

            outType = ENumericTokenType.Integer;

            bool IsPositive          = true;
            bool Exponent_IsPositive = true;
            bool Decimal             = false;
            bool HasExponent         = false;

            int Start = Stream.Position;

            if (Stream.Next == CHAR_HYPHEN_MINUS)
            {
                IsPositive = false;
                Stream.Consume();
            }
            else if (Stream.Next == CHAR_PLUS_SIGN)
            {
                Stream.Consume();
            }

            if (!Stream.Consume_While(Is_Ascii_Digit, out ReadOnlySpan <char> Integer))
            {
                throw new CssParserException(ParserErrors.PARSING_FAILED);
            }

            if (Stream.Next == CHAR_FULL_STOP)
            {
                outType = ENumericTokenType.Number;
                Decimal = true;
                Stream.Consume();
            }

            if (!Stream.Consume_While(Is_Ascii_Digit, out ReadOnlySpan <char> Fraction) && Decimal)
            {
                throw new CssParserException(ParserErrors.PARSING_FAILED);
            }

            if (Stream.Next == CHAR_E_UPPER || Stream.Next == CHAR_E_LOWER)
            {
                HasExponent = true;
                outType     = ENumericTokenType.Number;
                Stream.Consume();
            }

            if (Stream.Next == CHAR_HYPHEN_MINUS)
            {
                Exponent_IsPositive = false;
                Stream.Consume();
            }
            else if (Stream.Next == CHAR_PLUS_SIGN)
            {
                Stream.Consume();
            }

            if (!Stream.Consume_While(Is_Ascii_Digit, out ReadOnlySpan <char> Exponent) && HasExponent)
            {
                throw new CssParserException(ParserErrors.PARSING_FAILED);
            }

            int len = Stream.Position - Start;

            outResult = Stream.AsMemory().Slice(Start, len);

            //return S * (I + (F * Math.Pow(10, -D))) * Math.Pow(10, T*E);
            if (Decimal)
            {
                outNumber = ParsingCommon.ToDecimal(IsPositive ? 1 : -1, Integer, Fraction, Exponent_IsPositive ? 1 : -1, Exponent);
            }
            else
            {
                outNumber = ParsingCommon.ToInteger(IsPositive ? 1 : -1, Integer, Exponent_IsPositive ? 1 : -1, Exponent);
            }
        }
예제 #3
0
        public static string Consume_HTTP_Quoted_String(DataConsumer <char> Stream, bool bExtract_Value_Flag = false)
        {/* Docs: https://fetch.spec.whatwg.org/#collect-an-http-quoted-string */
            var positionStart = Stream.LongPosition;
            var sb            = bExtract_Value_Flag ? new StringBuilder() : null;

            /* 3) Assert: the code point at position within input is U+0022 ("). */
            if (Stream.Next != CHAR_QUOTATION_MARK)
            {
                throw new DOM.Exceptions.DomSyntaxError($"Expected quotation mark @\"{ParsingCommon.Get_Location(Stream)}");
            }

            Stream.Consume();
            while (true)
            {
                /* 1) Append the result of collecting a sequence of code points that are not U+0022 (") or U+005C (\) from input, given position, to value. */
                Stream.Consume_While(c => c != CHAR_EQUALS && c != CHAR_REVERSE_SOLIDUS, out ReadOnlyMemory <char> outConsumed);
                if (sb != null)
                {
                    sb.Append(outConsumed.ToString());
                }

                if (Stream.atEnd)
                {
                    break;
                }

                var quoteOrBackslash = Stream.Next;
                Stream.Consume();
                if (quoteOrBackslash == CHAR_REVERSE_SOLIDUS)
                {
                    if (Stream.atEnd)
                    {
                        if (sb != null)
                        {
                            sb.Append(CHAR_REVERSE_SOLIDUS);
                        }
                        break;
                    }

                    if (sb != null)
                    {
                        sb.Append(Stream.Next);
                    }
                    Stream.Consume();
                }
                else
                {
                    /* 1) Assert: quoteOrBackslash is U+0022 ("). */
                    if (quoteOrBackslash != CHAR_QUOTATION_MARK)
                    {
                        throw new DOM.Exceptions.DomSyntaxError($"Expected quotation mark @\"{ParsingCommon.Get_Location(Stream)}");
                    }

                    break;
                }
            }

            if (bExtract_Value_Flag)
            {
                return(sb.ToString());
            }

            /* 7) Return the code points from positionStart to position, inclusive, within input. */
            return(Stream.AsMemory().Slice((int)positionStart, (int)(Stream.LongPosition - positionStart)).ToString());
        }