Exemplo n.º 1
0
 public ValuedTokenBase(ECssTokenType Type, ReadOnlySpan <char> Value, bool AutoLowercase = true) : base(Type)
 {
     if (AutoLowercase)
     {// CSS is case-insensitive
         this.Value = StringCommon.Transform(Value, UnicodeCommon.To_ASCII_Lower_Alpha);
     }
     else
     {
         this.Value = Value.ToString();
     }
 }
Exemplo n.º 2
0
        // slice Blob into byte-ranged chunks
        public Blob slice(long?start, long?end, string contentType = null)
        {/* Docs: https://w3c.github.io/FileAPI/#dfn-slice */
            ulong relativeStart = 0;

            if (start.HasValue)
            {
                if (start < 0)
                {
                    relativeStart = MathExt.Max(0, (ulong)((long)size + start.Value));
                }
                else
                {
                    relativeStart = MathExt.Min((ulong)start.Value, size);
                }
            }

            ulong relativeEnd = size;

            if (end.HasValue)
            {
                if (end < 0)
                {
                    relativeEnd = MathExt.Max(0, (ulong)((long)size + end.Value));
                }
                else
                {
                    relativeEnd = MathExt.Min((ulong)end.Value, size);
                }
            }

            string relativeContentType = string.Empty;

            if (!string.IsNullOrEmpty(contentType))
            {
                relativeContentType = StringCommon.Transform(contentType.AsMemory(), UnicodeCommon.To_ASCII_Lower_Alpha);
            }

            ulong span = MathExt.Max(0, relativeEnd - relativeStart);

            return(new Blob(new BlobPart[] { AsMemory().Slice((int)relativeStart, (int)span) }, new BlobPropertyBag(relativeContentType)));
        }
Exemplo n.º 3
0
        public AtomicString(ReadOnlyMemory <char> Data, EAtomicStringFlags Flags)
        {
            Hash = new CachedValue <int>(() =>
            {
                if (0 != (Flags & EAtomicStringFlags.CaseInsensitive | EAtomicStringFlags.HasUppercase))
                {// This atomic-string wants to always be compared case insensitevly, but has uppercase character in it's string
                    return(StringCommon.Transform(Data, UnicodeCommon.To_ASCII_Lower_Alpha).GetHashCode(StringComparison.InvariantCulture));
                }
                else
                {
                    //return new string(Data.ToArray()).GetHashCode();
                    return(Data.Pin().GetHashCode());
                }
            });

            Hash_Lower = new CachedValue <int>(() =>
            {
                /* Check if our string actually has uppercased characters, if it does then we need to lowercase it and get its hash */
                if (0 != (Flags & EAtomicStringFlags.HasUppercase))
                {// This atomic string has uppercase characters so we do infact need to create the caseless-hash
                    return(StringCommon.Transform(Data, UnicodeCommon.To_ASCII_Lower_Alpha).GetHashCode(StringComparison.Ordinal));
                }

                return(GetHashCode());
            });

            this.Data = Data;

            /*this.Data = new Memory<char>(Data.Length);
             * Data.CopyTo(this.Data);*/

            this.Flags = Flags;

            if (StringCommon.Contains(Data.Span, c => char.IsUpper(c)))
            {
                Flags |= EAtomicStringFlags.HasUppercase;
            }
        }
Exemplo n.º 4
0
        public void TransformTest(string Expected, string Input)
        {
            string Actual = StringCommon.Transform(Input, UnicodeCommon.To_ASCII_Lower_Alpha);

            Assert.Equal(Expected, Actual);
        }
Exemplo n.º 5
0
 public Blob(IReadOnlyCollection <BlobPart> blobParts, BlobPropertyBag options = null)
 {
     data = process_blob_parts(blobParts, options);
     size = (uint)data.Length;
     type = StringCommon.Transform(options.type.AsMemory(), UnicodeCommon.To_ASCII_Lower_Alpha);
 }
Exemplo n.º 6
0
        /// <summary>
        /// Resolves an elements IDL-exposed autofill value
        /// </summary>
        /// <param name="element"></param>
        /// <param name="outFieldName">The autofill field name specifies the specific kind of data expected in the field, e.g. "street-address" or "cc-exp".</param>
        /// <param name="outHint">The autofill hint set identifies what address or contact information type the user agent is to look at, e.g. "shipping fax" or "billing".</param>
        /// <param name="outScope">The autofill scope identifies the group of fields whose information concerns the same subject, and consists of the autofill hint set with, if applicable, the "section-*" prefix, e.g. "billing", "section-parent shipping", or "section-child shipping home".</param>
        public static void Resolve_Autofill(FormAssociatedElement element, out EAutofill outFieldName, out IReadOnlyList <string> outHint, out IReadOnlyList <string> outScope, out string outidlValue)
        {/* Docs: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill-processing-model */
            AttributeValue  autocomplete = element.getAttribute(EAttributeName.Autocomplete);
            EAutofillMantle afMantle     = Get_Autofill_Mantle(element);

            if (autocomplete != null)
            {
                /* 2) Let tokens be the result of splitting the attribute's value on ASCII whitespace. */
                //var tokens = DOMCommon.Parse_Ordered_Set(autocomplete.Get_String().AsMemory());
                string acString  = StringCommon.Transform(autocomplete.AsString().AsMemory(), To_ASCII_Lower_Alpha);
                var    tokenList = new List <string>(DOMCommon.Parse_Ordered_Set(acString.AsMemory()).Select(o => o.ToString()));
                tokenList.Reverse();
                DataConsumer <string> Stream = new DataConsumer <string>(tokenList.ToArray(), null);

                /* 3) If tokens is empty, then jump to the step labeled default. */
                if (Stream.Length > 0)
                {
                    /* 4) Let index be the index of the last token in tokens. */
                    //int index = tokens.Count - 1;

                    /* 5) If the indexth token in tokens is not an ASCII case-insensitive match for one of the tokens given in the first column of the following table,
                     * or if the number of tokens in tokens is greater than the maximum number given in the cell in the second column of that token's row, then jump to the step labeled default.
                     * Otherwise, let field be the string given in the cell of the first column of the matching row, and let category be the value of the cell in the third column of that same row. */

                    //var key = tokens[index];
                    string            key        = Stream.Next;
                    EAutofill         afValue    = Lookup.Enum <EAutofill>(key);
                    EnumData          afData     = Lookup.Data(afValue);
                    int               maxTokens  = (int)afData[0];
                    EAutofillCategory afCategory = (EAutofillCategory)afData[1];

                    /* ...if the number of tokens in tokens is greater than the maximum number given in the cell in the second column of that token's row, then jump to the step labeled default. */
                    if (Stream.Length <= maxTokens)
                    {
                        var field    = afValue;
                        var category = afCategory;

                        /* 6) If category is Off or Automatic but the element's autocomplete attribute is wearing the autofill anchor mantle, then jump to the step labeled default. */
                        if ((category == EAutofillCategory.Off || category == EAutofillCategory.Automatic) && afMantle == EAutofillMantle.Anchor)
                        {/* "Jump" to default */
                        }
                        else
                        {
                            /* 7) If category is Off, let the element's autofill field name be the string "off", let its autofill hint set be empty, and let its IDL-exposed autofill value be the string "off". Then, return. */
                            if (category == EAutofillCategory.Off)
                            {
                                outFieldName = EAutofill.Off;
                                outHint      = Array.Empty <string>();
                                outScope     = Array.Empty <string>();
                                outidlValue  = "off";
                                return;
                            }

                            /* 8) If category is Automatic, let the element's autofill field name be the string "on", let its autofill hint set be empty, and let its IDL-exposed autofill value be the string "on". Then, return. */
                            if (category == EAutofillCategory.Automatic)
                            {
                                outFieldName = EAutofill.On;
                                outHint      = Array.Empty <string>();
                                outScope     = Array.Empty <string>();
                                outidlValue  = "on";
                                return;
                            }

                            /* 9) Let scope tokens be an empty list. */
                            LinkedList <string> scopeTokens = new LinkedList <string>();
                            /* 10) Let hint tokens be an empty set. */
                            LinkedList <string> hintTokens = new LinkedList <string>();
                            /* 11) Let IDL value have the same value as field. */
                            string idlValue = Lookup.Keyword(field);

                            /* 12) If the indexth token in tokens is the first entry, then skip to the step labeled done. */
                            //if (index == 0)
                            if (Stream.Remaining > 1)
                            {
                                /* 13) Decrement index by one. */
                                //index--;
                                Stream.Consume();
                                /* 14) If category is Contact and the indexth token in tokens is an ASCII case-insensitive match for one of the strings in the following list, then run the substeps that follow: */
                                if (category == EAutofillCategory.Contact)
                                {
                                    if (Lookup.TryEnum(Stream.Next, out EAutofillContact hint))
                                    {
                                        /* 1) Let contact be the matching string from the list above. */
                                        string contact = Stream.Next;
                                        /* 2) Insert contact at the start of scope tokens. */
                                        scopeTokens.AddFirst(contact);
                                        /* 3) Add contact to hint tokens. */
                                        hintTokens.AddLast(contact);
                                        /* 4) Let IDL value be the concatenation of contact, a U+0020 SPACE character, and the previous value of IDL value (which at this point will always be field). */
                                        idlValue = string.Concat(Stream.Next, CHAR_SPACE, idlValue);
                                        /* 5) If the indexth entry in tokens is the first entry, then skip to the step labeled done. */
                                        if (Stream.Remaining > 1)
                                        {
                                            /* 6) Decrement index by one. */
                                            //index--;
                                            Stream.Consume();
                                        }
                                    }
                                }
                                /* 15) If the indexth token in tokens is an ASCII case-insensitive match for one of the strings in the following list, then run the substeps that follow: */
                                if (Lookup.Is_Declared <EAutofillMode>(Stream.Next))
                                {
                                    /* 1) Let mode be the matching string from the list above. */
                                    var mode = Stream.Next;
                                    /* 2) Insert mode at the start of scope tokens. */
                                    scopeTokens.AddFirst(mode);
                                    /* 3) Add mode to hint tokens. */
                                    hintTokens.AddLast(mode);
                                    /* 4) Let IDL value be the concatenation of mode, a U+0020 SPACE character, and the previous value of IDL value (which at this point will either be field or the concatenation of contact, a space, and field). */
                                    idlValue = string.Concat(Stream.Next, CHAR_SPACE, idlValue);
                                    /* 5) If the indexth entry in tokens is the first entry, then skip to the step labeled done. */
                                    if (Stream.Remaining > 1)
                                    {
                                        /* 6) Decrement index by one. */
                                        //index--;
                                        Stream.Consume();
                                    }
                                }
                            }

                            /* 16) If the indexth entry in tokens is not the first entry, then jump to the step labeled default. */
                            if (Stream.Remaining == 1)
                            {
                                /* 17) If the first eight characters of the indexth token in tokens are not an ASCII case-insensitive match for the string "section-", then jump to the step labeled default. */
                                if (Stream.Next.StartsWith("section-"))
                                {
                                    /* 18) Let section be the indexth token in tokens, converted to ASCII lowercase. */
                                    string section = Stream.Next;/* Already in ascii lowercase */
                                    /* 19) Insert section at the start of scope tokens. */
                                    scopeTokens.AddFirst(section);
                                    /* 20) Let IDL value be the concatenation of section, a U+0020 SPACE character, and the previous value of IDL value. */
                                    idlValue = string.Concat(Stream.Next, CHAR_SPACE, idlValue);
                                }


                                /* 21) Done: Let the element's autofill hint set be hint tokens. */
                                outHint = hintTokens.ToArray();

                                /* 22) Let the element's autofill scope be scope tokens. */
                                outScope = scopeTokens.ToArray();

                                /* 23) Let the element's autofill field name be field. */
                                outFieldName = field;

                                /* 24) Let the element's IDL-exposed autofill value be IDL value. */
                                outidlValue = idlValue;

                                /* 25) Return. */
                                return;
                            }
                        }
                    }
                }
            }

            /* 26) Default: Let the element's IDL-exposed autofill value be the empty string, and its autofill hint set and autofill scope be empty. */
            outidlValue = string.Empty;
            outHint     = Array.Empty <string>();
            outScope    = Array.Empty <string>();

            /* 27) If the element's autocomplete attribute is wearing the autofill anchor mantle, then let the element's autofill field name be the empty string and return. */
            if (afMantle == EAutofillMantle.Anchor)
            {
                outFieldName = EAutofill.EMPTY;
                return;
            }

            /* 28) Let form be the element's form owner, if any, or null otherwise. */
            var form = element.form;

            /* 29) If form is not null and form's autocomplete attribute is in the off state, then let the element's autofill field name be "off".
             * Otherwise, let the element's autofill field name be "on". */

            outFieldName = (form != null && autocomplete != null && autocomplete.AsEnum <EAutoComplete>() == EAutoComplete.Off) ? EAutofill.Off : EAutofill.On;
        }