Remove unnecessary LINQ usage from System.Text.Json (dotnet/corefx#41553)
authorStephen Toub <stoub@microsoft.com>
Mon, 7 Oct 2019 22:01:26 +0000 (18:01 -0400)
committerGitHub <noreply@github.com>
Mon, 7 Oct 2019 22:01:26 +0000 (18:01 -0400)
* Remove unnecessary LINQ usage from System.Text.Json

* Fix netstandard build

Commit migrated from https://github.com/dotnet/corefx/commit/2d69a2494b3c1602d9332bab3794e00d1b4858c7

src/libraries/System.Text.Json/src/System.Text.Json.csproj
src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs [new file with mode: 0644]
src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.Traversal.cs
src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonNode.TraversalHelpers.cs
src/libraries/System.Text.Json/src/System/Text/Json/Node/JsonObject.cs

index 661f0c0..8c9891a 100644 (file)
     <Compile Include="System\Text\Json\Writer\Utf8JsonWriter.WriteValues.UnsignedNumber.cs" />
   </ItemGroup>
   <ItemGroup Condition="'$(TargetsNETStandard)' == 'true' OR '$(TargetsNetFx)' == 'true'">
+    <Compile Include="System\Collections\Generic\StackExtensions.netstandard.cs" />
     <!-- Common or Common-branched source files -->
     <Compile Include="$(CommonPath)\System\Buffers\ArrayBufferWriter.cs">
       <Link>Common\System\Buffers\ArrayBufferWriter.cs</Link>
diff --git a/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs b/src/libraries/System.Text.Json/src/System/Collections/Generic/StackExtensions.netstandard.cs
new file mode 100644 (file)
index 0000000..f53c2ab
--- /dev/null
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+    /// <summary>Polyfills for <see cref="Stack{T}"/>.</summary>
+    internal static class StackExtensions
+    {
+        public static bool TryPeek<T>(this Stack<T> stack, out T result)
+        {
+            if (stack.Count > 0)
+            {
+                result = stack.Peek();
+                return true;
+            }
+
+            result = default;
+            return false;
+        }
+
+        public static bool TryPop<T>(this Stack<T> stack, out T result)
+        {
+            if (stack.Count > 0)
+            {
+                result = stack.Pop();
+                return true;
+            }
+
+            result = default;
+            return false;
+        }
+    }
+}
index e093aa4..c606fa0 100644 (file)
@@ -35,18 +35,15 @@ namespace System.Text.Json
 
             recursionStack.Push(new KeyValuePair<string, JsonElement?>(null, jsonElement));
 
-            while (recursionStack.Any())
+            while (recursionStack.TryPop(out KeyValuePair<string, JsonElement?> currentPair))
             {
-                KeyValuePair<string, JsonElement?> currentPair = recursionStack.Peek();
                 JsonElement? currentJsonElement = currentPair.Value;
-                recursionStack.Pop();
 
                 if (!currentJsonElement.HasValue)
                 {
                     // Current object/array is finished and can be added to its parent:
 
-                    KeyValuePair<string, JsonNode> nodePair = currentNodes.Peek();
-                    currentNodes.Pop();
+                    KeyValuePair<string, JsonNode> nodePair = currentNodes.Pop();
 
                     Debug.Assert(nodePair.Value is JsonArray || nodePair.Value is JsonObject);
 
@@ -66,7 +63,7 @@ namespace System.Text.Json
                         // Add end of object marker:
                         recursionStack.Push(new KeyValuePair<string, JsonElement?>(null, null));
 
-                        // Add properties to recursion stack. Reverse enumerator to keep properties order:
+                        // Add properties to recursion stack. Reverse enumerate to keep properties order:
                         foreach (JsonProperty property in currentJsonElement.Value.EnumerateObject().Reverse())
                         {
                             recursionStack.Push(new KeyValuePair<string, JsonElement?>(property.Name, property.Value));
@@ -81,7 +78,7 @@ namespace System.Text.Json
                         // Add end of array marker:
                         recursionStack.Push(new KeyValuePair<string, JsonElement?>(null, null));
 
-                        // Add elements to recursion stack. Reverse enumerator to keep items order:
+                        // Add elements to recursion stack. Reverse enumerate to keep items order:
                         foreach (JsonElement element in currentJsonElement.Value.EnumerateArray().Reverse())
                         {
                             recursionStack.Push(new KeyValuePair<string, JsonElement?>(null, element));
@@ -134,11 +131,7 @@ namespace System.Text.Json
             while (reader.Read())
             {
                 JsonTokenType tokenType = reader.TokenType;
-                KeyValuePair<string, JsonNode> currentPair = new KeyValuePair<string, JsonNode>();
-                if (currentNodes.Any())
-                {
-                    currentPair = currentNodes.Peek();
-                }
+                currentNodes.TryPeek(out KeyValuePair<string, JsonNode> currentPair);
 
                 void AddNewPair(JsonNode jsonNode, bool keepInCurrentNodes = false)
                 {
@@ -234,11 +227,8 @@ namespace System.Text.Json
             var recursionStack = new Stack<RecursionStackFrame>();
             recursionStack.Push(new RecursionStackFrame(null, this));
 
-            while (recursionStack.Any())
+            while (recursionStack.TryPop(out RecursionStackFrame currentFrame))
             {
-                RecursionStackFrame currentFrame = recursionStack.Peek();
-                recursionStack.Pop();
-
                 if (currentFrame.PropertyValue == null)
                 {
                     // Current object/array is finished.
@@ -271,7 +261,7 @@ namespace System.Text.Json
                         // Add end of object marker:
                         recursionStack.Push(new RecursionStackFrame(null, null, JsonValueKind.Object));
 
-                        // Add properties to recursion stack. Reverse enumerator to keep properties order:
+                        // Add properties to recursion stack. Reverse enumerate to keep properties order:
                         foreach (KeyValuePair<string, JsonNode> jsonProperty in jsonObject.Reverse())
                         {
                             recursionStack.Push(new RecursionStackFrame(jsonProperty.Key, jsonProperty.Value));
@@ -283,10 +273,10 @@ namespace System.Text.Json
                         // Add end of array marker:
                         recursionStack.Push(new RecursionStackFrame(null, null, JsonValueKind.Array));
 
-                        // Add items to recursion stack. Reverse enumerator to keep items order:
-                        foreach (JsonNode item in jsonArray.Reverse())
+                        // Add items to recursion stack. Reverse enumerate to keep items order:
+                        for (int i = jsonArray.Count - 1; i >= 0; i--)
                         {
-                            recursionStack.Push(new RecursionStackFrame(null, item));
+                            recursionStack.Push(new RecursionStackFrame(null, jsonArray[i]));
                         }
                         break;
                     case JsonString jsonString:
index d5dd531..c29e8dd 100644 (file)
@@ -4,7 +4,6 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
 
 namespace System.Text.Json
 {
@@ -19,10 +18,8 @@ namespace System.Text.Json
             ref JsonNode toReturn,
             DuplicatePropertyNameHandlingStrategy duplicatePropertyNameHandling = DuplicatePropertyNameHandlingStrategy.Replace)
         {
-            if (currentNodes.Any())
+            if (currentNodes.TryPeek(out KeyValuePair<string, JsonNode> parentPair))
             {
-                KeyValuePair<string, JsonNode> parentPair = currentNodes.Peek();
-
                 // Parent needs to be JsonObject or JsonArray
                 Debug.Assert(parentPair.Value is JsonObject || parentPair.Value is JsonArray);
 
index 1ce9144..5ead7c9 100644 (file)
@@ -4,7 +4,6 @@
 
 using System.Collections;
 using System.Collections.Generic;
-using System.Linq;
 
 namespace System.Text.Json
 {
@@ -540,7 +539,15 @@ namespace System.Text.Json
         /// <summary>
         ///  A collection containing the property values of JSON object.
         /// </summary>
-        public IReadOnlyCollection<JsonNode> GetPropertyValues() => _dictionary.Values.Select(jsonObjectProperty => jsonObjectProperty.Value).ToList();
+        public IReadOnlyCollection<JsonNode> GetPropertyValues()
+        {
+            var list = new List<JsonNode>(_dictionary.Count);
+            foreach (KeyValuePair<string, JsonObjectProperty> item in _dictionary)
+            {
+                list.Add(item.Value.Value);
+            }
+            return list;
+        }
 
         /// <summary>
         ///   Returns an enumerator that iterates through the JSON object properties.