diff --git a/src/FSharp.Data.Html.Core/HtmlCssSelectors.fs b/src/FSharp.Data.Html.Core/HtmlCssSelectors.fs index ff8e9cead..13bb0db24 100644 --- a/src/FSharp.Data.Html.Core/HtmlCssSelectors.fs +++ b/src/FSharp.Data.Html.Core/HtmlCssSelectors.fs @@ -83,20 +83,18 @@ module internal HtmlCssSelectors = | c -> failwithf "Invalid css selector syntax at: %s" (new String(Array.ofList c)) let (|StartsWith|_|) (s: string) (items: char list) = - let candidates = s.ToCharArray() - - if items.Length < candidates.Length then + if items.Length < s.Length then None else - let start = items |> Seq.take (candidates.Length) |> Seq.toList + let start = items |> Seq.take s.Length - if (Seq.compareWith (fun a b -> (int a) - (int b)) start candidates) = 0 then + if (Seq.compareWith (fun a b -> (int a) - (int b)) start s) = 0 then Some(items |> Seq.skip s.Length |> Seq.toList) else None let (|TokenStr|_|) (s: string) x = - let chars = s.ToCharArray() |> Array.toList + let chars = List.ofSeq s let rec equal x s = match x, s with @@ -208,7 +206,7 @@ module internal HtmlCssSelectors = member public x.Tokenize(pCssSelector: string) = cssSelector <- pCssSelector - source <- cssSelector.ToCharArray() |> Array.toList + source <- List.ofSeq cssSelector charCount <- source.Length tokenize () diff --git a/src/FSharp.Data.Html.Core/HtmlOperations.fs b/src/FSharp.Data.Html.Core/HtmlOperations.fs index 7a172ca33..4f6fb3246 100644 --- a/src/FSharp.Data.Html.Core/HtmlOperations.fs +++ b/src/FSharp.Data.Html.Core/HtmlOperations.fs @@ -367,7 +367,7 @@ module HtmlNode = let selectedNodes = filterByAttr level acc name (fun v -> let chars = - v.ToCharArray() + v |> Seq.skipWhile (fun c -> c = '\'') |> Seq.takeWhile Char.IsLetter |> Seq.toArray diff --git a/src/FSharp.Data.Html.Core/HtmlParser.fs b/src/FSharp.Data.Html.Core/HtmlParser.fs index 011f2986d..2c83a391d 100644 --- a/src/FSharp.Data.Html.Core/HtmlParser.fs +++ b/src/FSharp.Data.Html.Core/HtmlParser.fs @@ -1113,7 +1113,10 @@ module internal HtmlParser = parse' docType elements expectedTagEnd parentTagName (TagEnd expectedTagEnd :: tokens) | TagEnd name :: rest when name <> expectedTagEnd - && (name <> (new String(expectedTagEnd.ToCharArray() |> Array.rev))) + && (name + <> (new String( + Array.init expectedTagEnd.Length (fun i -> expectedTagEnd.[expectedTagEnd.Length - 1 - i]) + ))) -> // ignore this token if not the expected end tag (or it's reverse, eg:
  • ) parse' docType elements expectedTagEnd parentTagName rest diff --git a/src/FSharp.Data.Runtime.Utilities/TextConversions.fs b/src/FSharp.Data.Runtime.Utilities/TextConversions.fs index 9ff5d65ed..798b0b8e5 100644 --- a/src/FSharp.Data.Runtime.Utilities/TextConversions.fs +++ b/src/FSharp.Data.Runtime.Utilities/TextConversions.fs @@ -104,11 +104,14 @@ type TextConversions private () = // No adorners found, return original string to avoid allocation value else - // Adorners found, perform filtering - String( - value.ToCharArray() - |> Array.filter (not << TextConversions.DefaultRemovableAdornerCharacters.Contains) - ) + // Adorners found, perform filtering via StringBuilder to avoid ToCharArray allocation + let sb = System.Text.StringBuilder(value.Length) + + for c in value do + if not (TextConversions.DefaultRemovableAdornerCharacters.Contains(c)) then + sb.Append(c) |> ignore + + sb.ToString() /// Turns empty or null string value into None, otherwise returns Some static member AsString str =