Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/Newtonsoft.Json.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
authorJamesNK <james@newtonking.com>2011-05-28 04:46:38 +0400
committerJamesNK <james@newtonking.com>2011-05-28 04:46:38 +0400
commitb3cc3e88acbf7fae91ed2084a95b4cfebe35907e (patch)
tree8dae2d59a85514edacd5e5c2895426f2646fc8c9 /Src
parentcc44f53c1a2df64b6d1125c891ba0b997fbe7c1d (diff)
-Rewrote LINQ to JSON internals to use lists and dictionaries rather than a linked list
-Moved JPropertyDescriptor to Newtonsoft.Json.Linq namespace
Diffstat (limited to 'Src')
-rw-r--r--Src/Newtonsoft.Json.Tests/Linq/ComponentModel/JPropertyDescriptorTests.cs1
-rw-r--r--Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs8
-rw-r--r--Src/Newtonsoft.Json.Tests/PerformanceTests.cs25
-rw-r--r--Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs2
-rw-r--r--Src/Newtonsoft.Json/Linq/JArray.cs7
-rw-r--r--Src/Newtonsoft.Json/Linq/JConstructor.cs6
-rw-r--r--Src/Newtonsoft.Json/Linq/JContainer.cs370
-rw-r--r--Src/Newtonsoft.Json/Linq/JObject.cs85
-rw-r--r--Src/Newtonsoft.Json/Linq/JProperty.cs75
-rw-r--r--Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs (renamed from Src/Newtonsoft.Json/Linq/ComponentModel/JPropertyDescriptor.cs)2
-rw-r--r--Src/Newtonsoft.Json/Linq/JToken.cs37
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj2
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj2
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj2
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj2
-rw-r--r--Src/Newtonsoft.Json/Newtonsoft.Json.csproj3
-rw-r--r--Src/Newtonsoft.Json/Properties/AssemblyInfo.cs2
-rw-r--r--Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs1
-rw-r--r--Src/Newtonsoft.Json/Utilities/CollectionUtils.cs34
19 files changed, 333 insertions, 333 deletions
diff --git a/Src/Newtonsoft.Json.Tests/Linq/ComponentModel/JPropertyDescriptorTests.cs b/Src/Newtonsoft.Json.Tests/Linq/ComponentModel/JPropertyDescriptorTests.cs
index 32d88eb..e22adca 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/ComponentModel/JPropertyDescriptorTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/ComponentModel/JPropertyDescriptorTests.cs
@@ -29,7 +29,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
-using Newtonsoft.Json.Linq.ComponentModel;
using Newtonsoft.Json.Linq;
namespace Newtonsoft.Json.Tests.Linq.ComponentModel
diff --git a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs
index efc2b52..ebf9c95 100644
--- a/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs
+++ b/Src/Newtonsoft.Json.Tests/Linq/JArrayTests.cs
@@ -165,7 +165,7 @@ Parameter name: arrayIndex")]
}
[Test]
- [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"index is equal to or greater than Count.
+ [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Index is equal to or greater than Count.
Parameter name: index")]
public void RemoveAtOutOfRangeIndexShouldError()
{
@@ -174,7 +174,7 @@ Parameter name: index")]
}
[Test]
- [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"index is less than 0.
+ [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Index is less than 0.
Parameter name: index")]
public void RemoveAtNegativeIndexShouldError()
{
@@ -253,7 +253,7 @@ Parameter name: index")]
}
[Test]
- [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Specified argument was out of the range of valid values.
+ [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index")]
public void InsertNegativeIndexShouldThrow()
{
@@ -262,7 +262,7 @@ Parameter name: index")]
}
[Test]
- [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Specified argument was out of the range of valid values.
+ [ExpectedException(typeof(ArgumentOutOfRangeException), ExpectedMessage = @"Index must be within the bounds of the List.
Parameter name: index")]
public void InsertOutOfRangeIndexShouldThrow()
{
diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
index 7667682..54a7ba9 100644
--- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
+++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs
@@ -121,6 +121,31 @@ namespace Newtonsoft.Json.Tests
return result;
}
+ [Test]
+ public void BuildJObject()
+ {
+ JObject o = new JObject();
+ for (int i = 0; i < 200; i++)
+ {
+ o[i.ToString()] = i;
+ }
+ string jsonText = o.ToString();
+
+ // this is extremely slow with 5000 interations
+ int interations = 100;
+
+ TimeOperation(() =>
+ {
+ JObject oo = null;
+ for (int i = 0; i < interations; i++)
+ {
+ oo = JObject.Parse(jsonText);
+ }
+
+ return oo;
+ }, "JObject");
+ }
+
private void SerializeSize(object value)
{
// this is extremely slow with 5000 interations
diff --git a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
index 1c4dd3e..d26198c 100644
--- a/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json.Tests/Properties/AssemblyInfo.cs
@@ -41,5 +41,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.0.2.13722")]
+[assembly: AssemblyFileVersion("4.0.2.13728")]
#endif
diff --git a/Src/Newtonsoft.Json/Linq/JArray.cs b/Src/Newtonsoft.Json/Linq/JArray.cs
index c8d478e..283de89 100644
--- a/Src/Newtonsoft.Json/Linq/JArray.cs
+++ b/Src/Newtonsoft.Json/Linq/JArray.cs
@@ -39,6 +39,13 @@ namespace Newtonsoft.Json.Linq
/// </summary>
public class JArray : JContainer, IList<JToken>
{
+ private IList<JToken> _values = new List<JToken>();
+
+ protected override IList<JToken> ChildrenTokens
+ {
+ get { return _values; }
+ }
+
/// <summary>
/// Gets the node type for this <see cref="JToken"/>.
/// </summary>
diff --git a/Src/Newtonsoft.Json/Linq/JConstructor.cs b/Src/Newtonsoft.Json/Linq/JConstructor.cs
index a875546..9b0175f 100644
--- a/Src/Newtonsoft.Json/Linq/JConstructor.cs
+++ b/Src/Newtonsoft.Json/Linq/JConstructor.cs
@@ -38,6 +38,12 @@ namespace Newtonsoft.Json.Linq
public class JConstructor : JContainer
{
private string _name;
+ private IList<JToken> _values = new List<JToken>();
+
+ protected override IList<JToken> ChildrenTokens
+ {
+ get { return _values; }
+ }
/// <summary>
/// Gets or sets the name of this constructor.
diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs
index 8dd4ca9..cdf7a7e 100644
--- a/Src/Newtonsoft.Json/Linq/JContainer.cs
+++ b/Src/Newtonsoft.Json/Linq/JContainer.cs
@@ -33,9 +33,6 @@ using System.Diagnostics;
using System.Globalization;
using System.ComponentModel;
using System.Collections.Specialized;
-#if !SILVERLIGHT
-using Newtonsoft.Json.Linq.ComponentModel;
-#endif
namespace Newtonsoft.Json.Linq
{
@@ -70,16 +67,11 @@ namespace Newtonsoft.Json.Linq
public event NotifyCollectionChangedEventHandler CollectionChanged;
#endif
- private JToken _content;
+ protected abstract IList<JToken> ChildrenTokens { get; }
+
private object _syncRoot;
private bool _busy;
- internal JToken Content
- {
- get { return _content; }
- set { _content = value; }
- }
-
internal JContainer()
{
}
@@ -88,15 +80,9 @@ namespace Newtonsoft.Json.Linq
{
ValidationUtils.ArgumentNotNull(other, "c");
- JToken content = other.Last;
- if (content != null)
+ foreach (JToken child in other)
{
- do
- {
- content = content._next;
- Add(content.CloneToken());
- }
- while (content != other.Last);
+ Add(child);
}
}
@@ -172,7 +158,7 @@ namespace Newtonsoft.Json.Linq
/// </value>
public override bool HasValues
{
- get { return (_content != null); }
+ get { return ChildrenTokens.Count > 0; }
}
internal bool ContentsEqual(JContainer container)
@@ -209,13 +195,7 @@ namespace Newtonsoft.Json.Linq
/// </value>
public override JToken First
{
- get
- {
- if (Last == null)
- return null;
-
- return Last._next;
- }
+ get { return ChildrenTokens.FirstOrDefault(); }
}
/// <summary>
@@ -226,8 +206,7 @@ namespace Newtonsoft.Json.Linq
/// </value>
public override JToken Last
{
- [DebuggerStepThrough]
- get { return _content; }
+ get { return ChildrenTokens.LastOrDefault(); }
}
/// <summary>
@@ -238,21 +217,7 @@ namespace Newtonsoft.Json.Linq
/// </returns>
public override JEnumerable<JToken> Children()
{
- return new JEnumerable<JToken>(ChildrenInternal());
- }
-
- internal IEnumerable<JToken> ChildrenInternal()
- {
- JToken first = First;
- JToken current = first;
- if (current == null)
- yield break;
-
- do
- {
- yield return current;
- }
- while ((current = current.Next) != null);
+ return new JEnumerable<JToken>(ChildrenTokens);
}
/// <summary>
@@ -264,7 +229,7 @@ namespace Newtonsoft.Json.Linq
/// </returns>
public override IEnumerable<T> Values<T>()
{
- return Children().Convert<JToken, T>();
+ return ChildrenTokens.Convert<JToken, T>();
}
/// <summary>
@@ -273,7 +238,7 @@ namespace Newtonsoft.Json.Linq
/// <returns>An <see cref="IEnumerable{JToken}"/> containing the descendant tokens of the <see cref="JToken"/>.</returns>
public IEnumerable<JToken> Descendants()
{
- foreach (JToken o in Children())
+ foreach (JToken o in ChildrenTokens)
{
yield return o;
JContainer c = o as JContainer;
@@ -292,37 +257,11 @@ namespace Newtonsoft.Json.Linq
return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
}
- internal virtual void AddItem(bool isLast, JToken previous, JToken item)
- {
- CheckReentrancy();
-
- ValidateToken(item, null);
-
- item = EnsureParentToken(item);
-
- JToken next = (previous != null) ? previous._next : item;
-
- item.Parent = this;
- item.Next = next;
-
- if (previous != null)
- previous.Next = item;
-
- if (isLast || previous == null)
- _content = item;
-
-#if !SILVERLIGHT
- if (ListChanged != null)
- OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, IndexOfItem(item)));
-#endif
-#if SILVERLIGHT || !(NET20 || NET35)
- if (CollectionChanged != null)
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, IndexOfItem(item)));
-#endif
- }
-
internal JToken EnsureParentToken(JToken item)
{
+ if (item == null)
+ return new JValue((object) null);
+
if (item.Parent != null)
{
item = item.CloneToken();
@@ -343,142 +282,157 @@ namespace Newtonsoft.Json.Linq
return item;
}
- internal void AddInternal(bool isLast, JToken previous, object content)
+ private class JTokenReferenceEqualityComparer : IEqualityComparer<JToken>
{
- if (IsMultiContent(content))
- {
- IEnumerable enumerable = (IEnumerable) content;
+ public static readonly JTokenReferenceEqualityComparer Instance = new JTokenReferenceEqualityComparer();
- JToken multiPrevious = previous;
- foreach (object c in enumerable)
- {
- AddInternal(isLast, multiPrevious, c);
- multiPrevious = (multiPrevious != null) ? multiPrevious._next : Last;
- }
- }
- else
+ public bool Equals(JToken x, JToken y)
{
- JToken item = CreateFromContent(content);
-
- AddItem(isLast, previous, item);
+ return ReferenceEquals(x, y);
}
- }
- internal int IndexOfItem(JToken item)
- {
- int index = 0;
- foreach (JToken token in Children())
+ public int GetHashCode(JToken obj)
{
- if (token == item)
- return index;
+ if (obj == null)
+ return 0;
- index++;
+ return obj.GetHashCode();
}
-
- return -1;
}
- internal virtual void InsertItem(int index, JToken item)
+ internal int IndexOfItem(JToken item)
{
- if (index == 0)
- {
- AddFirst(item);
- }
- else
- {
- JToken token = GetItem(index);
- AddInternal(false, token.Previous, item);
- }
+ return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
}
- internal virtual void RemoveItemAt(int index)
+ internal virtual void InsertItem(int index, JToken item)
{
- if (index < 0)
- throw new ArgumentOutOfRangeException("index", "index is less than 0.");
+ if (index > ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List.");
CheckReentrancy();
- int currentIndex = 0;
- foreach (JToken token in Children())
- {
- if (index == currentIndex)
- {
- token.Remove();
+ item = EnsureParentToken(item);
+
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ // haven't inserted new token yet so next token is still at the inserting index
+ JToken next = (index == ChildrenTokens.Count) ? null : ChildrenTokens[index];
+
+ ValidateToken(item, null);
+
+ item.Parent = this;
+
+ item.Previous = previous;
+ if (previous != null)
+ previous.Next = item;
+
+ item.Next = next;
+ if (next != null)
+ next.Previous = item;
+
+ ChildrenTokens.Insert(index, item);
#if !SILVERLIGHT
- OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
+ if (ListChanged != null)
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
#endif
#if SILVERLIGHT || !(NET20 || NET35)
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, token, index));
+ if (CollectionChanged != null)
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
#endif
-
- return;
- }
-
- currentIndex++;
- }
-
- throw new ArgumentOutOfRangeException("index", "index is equal to or greater than Count.");
}
- internal virtual bool RemoveItem(JToken item)
+ internal virtual void RemoveItemAt(int index)
{
- if (item == null || item.Parent != this)
- return false;
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+ if (index >= ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
CheckReentrancy();
- JToken content = _content;
+ JToken item = ChildrenTokens[index];
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+ if (previous != null)
+ previous.Next = next;
+ if (next != null)
+ next.Previous = previous;
- int itemIndex = 0;
- while (content._next != item)
- {
- itemIndex++;
- content = content._next;
- }
- if (content == item)
- {
- // token is containers last child
- _content = null;
- }
- else
- {
- if (_content == item)
- {
- _content = content;
- }
- content._next = item._next;
- }
item.Parent = null;
+ item.Previous = null;
item.Next = null;
+ ChildrenTokens.RemoveAt(index);
+
#if !SILVERLIGHT
- OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, itemIndex));
+ OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
#endif
#if SILVERLIGHT || !(NET20 || NET35)
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, itemIndex));
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
#endif
+ }
+
+ internal virtual bool RemoveItem(JToken item)
+ {
+ int index = IndexOfItem(item);
+ if (index >= 0)
+ {
+ RemoveItemAt(index);
+ return true;
+ }
- return true;
+ return false;
}
internal virtual JToken GetItem(int index)
{
- return Children().ElementAt(index);
+ return ChildrenTokens[index];
}
internal virtual void SetItem(int index, JToken item)
{
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+ if (index >= ChildrenTokens.Count)
+ throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
+
+ JToken existing = ChildrenTokens[index];
+
+ if (IsTokenUnchanged(existing, item))
+ return;
+
CheckReentrancy();
- JToken token = GetItem(index);
- token.Replace(item);
+ item = EnsureParentToken(item);
+
+ ValidateToken(item, existing);
+
+ JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+ JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+ item.Parent = this;
+
+ item.Previous = previous;
+ if (previous != null)
+ previous.Next = item;
+
+ item.Next = next;
+ if (next != null)
+ next.Previous = item;
+
+ ChildrenTokens[index] = item;
+
+ existing.Parent = null;
+ existing.Previous = null;
+ existing.Next = null;
#if !SILVERLIGHT
OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
#endif
#if SILVERLIGHT || !(NET20 || NET35)
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, token, index));
+ OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index));
#endif
}
@@ -486,23 +440,15 @@ namespace Newtonsoft.Json.Linq
{
CheckReentrancy();
- while (_content != null)
+ foreach (JToken item in ChildrenTokens)
{
- JToken o = _content;
-
- JToken next = o._next;
- if (o != _content || next != o._next)
- throw new InvalidOperationException("This operation was corrupted by external code.");
-
- if (next != o)
- o._next = next._next;
- else
- _content = null;
-
- next.Parent = null;
- next._next = null;
+ item.Parent = null;
+ item.Previous = null;
+ item.Next = null;
}
+ ChildrenTokens.Clear();
+
#if !SILVERLIGHT
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
#endif
@@ -516,51 +462,8 @@ namespace Newtonsoft.Json.Linq
if (existing == null || existing.Parent != this)
return;
- if (IsTokenUnchanged(existing, replacement))
- return;
-
- CheckReentrancy();
-
- replacement = EnsureParentToken(replacement);
-
- ValidateToken(replacement, existing);
-
- JToken content = _content;
-
- int itemIndex = 0;
- while (content._next != existing)
- {
- itemIndex++;
- content = content._next;
- }
-
- if (content == existing)
- {
- // token is containers last child
- _content = replacement;
- replacement._next = replacement;
- }
- else
- {
- if (_content == existing)
- {
- _content = replacement;
- }
- content._next = replacement;
- replacement._next = existing._next;
- }
-
- replacement.Parent = this;
-
- existing.Parent = null;
- existing.Next = null;
-
-#if !SILVERLIGHT
- OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, itemIndex));
-#endif
-#if SILVERLIGHT || !(NET20 || NET35)
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, replacement, existing, itemIndex));
-#endif
+ int index = IndexOfItem(existing);
+ SetItem(index, replacement);
}
internal virtual bool ContainsItem(JToken item)
@@ -580,7 +483,7 @@ namespace Newtonsoft.Json.Linq
throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
int index = 0;
- foreach (JToken token in Children())
+ foreach (JToken token in ChildrenTokens)
{
array.SetValue(token, arrayIndex + index);
index++;
@@ -589,7 +492,7 @@ namespace Newtonsoft.Json.Linq
internal virtual int CountItems()
{
- return Children().Count();
+ return ChildrenTokens.Count;
}
internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
@@ -619,9 +522,9 @@ namespace Newtonsoft.Json.Linq
/// Adds the specified content as children of this <see cref="JToken"/>.
/// </summary>
/// <param name="content">The content to be added.</param>
- public void Add(object content)
+ public virtual void Add(object content)
{
- AddInternal(true, Last, content);
+ AddInternal(ChildrenTokens.Count, content);
}
/// <summary>
@@ -630,7 +533,28 @@ namespace Newtonsoft.Json.Linq
/// <param name="content">The content to be added.</param>
public void AddFirst(object content)
{
- AddInternal(false, Last, content);
+ AddInternal(0, content);
+ }
+
+ internal void AddInternal(int index, object content)
+ {
+ if (IsMultiContent(content))
+ {
+ IEnumerable enumerable = (IEnumerable)content;
+
+ int multiIndex = index;
+ foreach (object c in enumerable)
+ {
+ AddInternal(multiIndex, c);
+ multiIndex++;
+ }
+ }
+ else
+ {
+ JToken item = CreateFromContent(content);
+
+ InsertItem(index, item);
+ }
}
internal JToken CreateFromContent(object content)
@@ -790,7 +714,7 @@ namespace Newtonsoft.Json.Linq
internal int ContentsHashCode()
{
int hashCode = 0;
- foreach (JToken item in Children())
+ foreach (JToken item in ChildrenTokens)
{
hashCode ^= item.GetDeepHashCode();
}
diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs
index 69946f5..c4c1adf 100644
--- a/Src/Newtonsoft.Json/Linq/JObject.cs
+++ b/Src/Newtonsoft.Json/Linq/JObject.cs
@@ -25,6 +25,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
#if !(NET35 || NET20 || WINDOWS_PHONE)
@@ -35,9 +36,6 @@ using System.Linq;
using System.IO;
using Newtonsoft.Json.Utilities;
using System.Globalization;
-#if !PocketPC && !SILVERLIGHT
-using Newtonsoft.Json.Linq.ComponentModel;
-#endif
namespace Newtonsoft.Json.Linq
{
@@ -52,6 +50,46 @@ namespace Newtonsoft.Json.Linq
, INotifyPropertyChanging
#endif
{
+ private class JPropertKeyedCollection : KeyedCollection<string, JToken>
+ {
+ public JPropertKeyedCollection(IEqualityComparer<string> comparer)
+ : base(comparer)
+ {
+ }
+
+ protected override string GetKeyForItem(JToken item)
+ {
+ return ((JProperty) item).Name;
+ }
+
+ protected override void InsertItem(int index, JToken item)
+ {
+ if (Dictionary == null)
+ {
+ base.InsertItem(index, item);
+ }
+ else
+ {
+ // need to override so that the dictionary key is always set rather than added
+ string keyForItem = GetKeyForItem(item);
+ Dictionary[keyForItem] = item;
+ Items.Insert(index, item);
+ }
+ }
+
+ public new IDictionary<string, JToken> Dictionary
+ {
+ get { return base.Dictionary; }
+ }
+ }
+
+ private JPropertKeyedCollection _properties = new JPropertKeyedCollection(StringComparer.Ordinal);
+
+ protected override IList<JToken> ChildrenTokens
+ {
+ get { return _properties; }
+ }
+
/// <summary>
/// Occurs when a property value changes.
/// </summary>
@@ -111,14 +149,18 @@ namespace Newtonsoft.Json.Linq
if (o.Type != JTokenType.Property)
throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
- // looping over all properties every time isn't good
- // need to think about performance here
- JProperty property = (JProperty)o;
- foreach (JProperty childProperty in Children())
+ JProperty newProperty = (JProperty) o;
+
+ if (existing != null)
{
- if (childProperty != existing && string.Equals(childProperty.Name, property.Name, StringComparison.Ordinal))
- throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, property.Name, GetType()));
+ JProperty existingProperty = (JProperty) existing;
+
+ if (newProperty.Name == existingProperty.Name)
+ return;
}
+
+ if (_properties.Dictionary != null && _properties.Dictionary.TryGetValue(newProperty.Name, out existing))
+ throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, newProperty.Name, GetType()));
}
internal void InternalPropertyChanged(JProperty childProperty)
@@ -159,7 +201,7 @@ namespace Newtonsoft.Json.Linq
/// <returns>An <see cref="IEnumerable{JProperty}"/> of this object's properties.</returns>
public IEnumerable<JProperty> Properties()
{
- return Children().Cast<JProperty>();
+ return ChildrenTokens.Cast<JProperty>();
}
/// <summary>
@@ -169,9 +211,14 @@ namespace Newtonsoft.Json.Linq
/// <returns>A <see cref="JProperty"/> with the specified name or null.</returns>
public JProperty Property(string name)
{
- return Properties()
- .Where(p => string.Equals(p.Name, name, StringComparison.Ordinal))
- .SingleOrDefault();
+ if (_properties.Dictionary == null)
+ return null;
+ if (name == null)
+ return null;
+
+ JToken property;
+ _properties.Dictionary.TryGetValue(name, out property);
+ return (JProperty)property;
}
/// <summary>
@@ -318,7 +365,7 @@ namespace Newtonsoft.Json.Linq
{
writer.WriteStartObject();
- foreach (JProperty property in ChildrenInternal())
+ foreach (JProperty property in ChildrenTokens)
{
property.WriteTo(writer, converters);
}
@@ -339,12 +386,12 @@ namespace Newtonsoft.Json.Linq
bool IDictionary<string, JToken>.ContainsKey(string key)
{
- return (Property(key) != null);
+ return _properties.Dictionary.ContainsKey(key);
}
ICollection<string> IDictionary<string, JToken>.Keys
{
- get { throw new NotImplementedException(); }
+ get { return _properties.Dictionary.Keys; }
}
/// <summary>
@@ -383,7 +430,7 @@ namespace Newtonsoft.Json.Linq
ICollection<JToken> IDictionary<string, JToken>.Values
{
- get { throw new NotImplementedException(); }
+ get { return _properties.Dictionary.Values; }
}
#endregion
@@ -421,7 +468,7 @@ namespace Newtonsoft.Json.Linq
throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
int index = 0;
- foreach (JProperty property in Properties())
+ foreach (JProperty property in ChildrenTokens)
{
array[arrayIndex + index] = new KeyValuePair<string, JToken>(property.Name, property.Value);
index++;
@@ -467,7 +514,7 @@ namespace Newtonsoft.Json.Linq
/// </returns>
public IEnumerator<KeyValuePair<string, JToken>> GetEnumerator()
{
- foreach (JProperty property in Properties())
+ foreach (JProperty property in ChildrenTokens)
{
yield return new KeyValuePair<string, JToken>(property.Name, property.Value);
}
diff --git a/Src/Newtonsoft.Json/Linq/JProperty.cs b/Src/Newtonsoft.Json/Linq/JProperty.cs
index 748a3ee..7749629 100644
--- a/Src/Newtonsoft.Json/Linq/JProperty.cs
+++ b/Src/Newtonsoft.Json/Linq/JProperty.cs
@@ -25,6 +25,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
@@ -39,8 +40,14 @@ namespace Newtonsoft.Json.Linq
/// </summary>
public class JProperty : JContainer
{
+ private readonly List<JToken> _content = new List<JToken>();
private readonly string _name;
+ protected override IList<JToken> ChildrenTokens
+ {
+ get { return _content; }
+ }
+
/// <summary>
/// Gets the property name.
/// </summary>
@@ -58,42 +65,24 @@ namespace Newtonsoft.Json.Linq
public JToken Value
{
[DebuggerStepThrough]
- get { return Content; }
+ get { return (ChildrenTokens.Count > 0) ? ChildrenTokens[0] : null; }
set
{
CheckReentrancy();
JToken newValue = value ?? new JValue((object) null);
- if (Content == null)
+ if (ChildrenTokens.Count == 0)
{
- newValue = EnsureParentToken(newValue);
-
- Content = newValue;
- Content.Parent = this;
- Content.Next = Content;
+ InsertItem(0, newValue);
}
else
{
- Content.Replace(newValue);
+ SetItem(0, newValue);
}
}
}
- internal override void ReplaceItem(JToken existing, JToken replacement)
- {
- if (IsTokenUnchanged(existing, replacement))
- return;
-
- if (Parent != null)
- ((JObject)Parent).InternalPropertyChanging(this);
-
- base.ReplaceItem(existing, replacement);
-
- if (Parent != null)
- ((JObject)Parent).InternalPropertyChanged(this);
- }
-
/// <summary>
/// Initializes a new instance of the <see cref="JProperty"/> class from another <see cref="JProperty"/> object.
/// </summary>
@@ -104,14 +93,6 @@ namespace Newtonsoft.Json.Linq
_name = other.Name;
}
- internal override void AddItem(bool isLast, JToken previous, JToken item)
- {
- if (Value != null)
- throw new Exception("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
-
- Value = item;
- }
-
internal override JToken GetItem(int index)
{
if (index != 0)
@@ -124,8 +105,17 @@ namespace Newtonsoft.Json.Linq
{
if (index != 0)
throw new ArgumentOutOfRangeException();
-
- Value = item;
+
+ if (IsTokenUnchanged(Value, item))
+ return;
+
+ if (Parent != null)
+ ((JObject)Parent).InternalPropertyChanging(this);
+
+ base.SetItem(0, item);
+
+ if (Parent != null)
+ ((JObject)Parent).InternalPropertyChanged(this);
}
internal override bool RemoveItem(JToken item)
@@ -140,7 +130,10 @@ namespace Newtonsoft.Json.Linq
internal override void InsertItem(int index, JToken item)
{
- throw new Exception("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+ if (Value != null)
+ throw new Exception("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+
+ base.InsertItem(0, item);
}
internal override bool ContainsItem(JToken item)
@@ -153,22 +146,6 @@ namespace Newtonsoft.Json.Linq
throw new Exception("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
- /// <summary>
- /// Returns a collection of the child tokens of this token, in document order.
- /// </summary>
- /// <returns>
- /// An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.
- /// </returns>
- public override JEnumerable<JToken> Children()
- {
- return new JEnumerable<JToken>(GetValueEnumerable());
- }
-
- private IEnumerable<JToken> GetValueEnumerable()
- {
- yield return Value;
- }
-
internal override bool DeepEquals(JToken node)
{
JProperty t = node as JProperty;
diff --git a/Src/Newtonsoft.Json/Linq/ComponentModel/JPropertyDescriptor.cs b/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
index 38db030..dd49c08 100644
--- a/Src/Newtonsoft.Json/Linq/ComponentModel/JPropertyDescriptor.cs
+++ b/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
@@ -28,7 +28,7 @@ using System;
using System.ComponentModel;
using Newtonsoft.Json.Utilities;
-namespace Newtonsoft.Json.Linq.ComponentModel
+namespace Newtonsoft.Json.Linq
{
/// <summary>
/// Represents a view of a <see cref="JProperty"/>.
diff --git a/Src/Newtonsoft.Json/Linq/JToken.cs b/Src/Newtonsoft.Json/Linq/JToken.cs
index 4e07dc6..a024f20 100644
--- a/Src/Newtonsoft.Json/Linq/JToken.cs
+++ b/Src/Newtonsoft.Json/Linq/JToken.cs
@@ -51,7 +51,8 @@ namespace Newtonsoft.Json.Linq
#endif
{
private JContainer _parent;
- internal JToken _next;
+ private JToken _previous;
+ private JToken _next;
private static JTokenEqualityComparer _equalityComparer;
private int? _lineNumber;
@@ -138,13 +139,7 @@ namespace Newtonsoft.Json.Linq
/// <value>The <see cref="JToken"/> that contains the next sibling token.</value>
public JToken Next
{
- get
- {
- if (_parent != null && _next != _parent.First)
- return _next;
-
- return null;
- }
+ get { return _next; }
internal set { _next = value; }
}
@@ -154,20 +149,8 @@ namespace Newtonsoft.Json.Linq
/// <value>The <see cref="JToken"/> that contains the previous sibling token.</value>
public JToken Previous
{
- get
- {
- if (_parent == null)
- return null;
-
- JToken parentNext = _parent.Content._next;
- JToken parentNextBefore = null;
- while (parentNext != this)
- {
- parentNextBefore = parentNext;
- parentNext = parentNext.Next;
- }
- return parentNextBefore;
- }
+ get { return _previous; }
+ internal set { _previous = value; }
}
internal JToken()
@@ -183,7 +166,8 @@ namespace Newtonsoft.Json.Linq
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
- _parent.AddInternal((Next == null), this, content);
+ int index = _parent.IndexOfItem(this);
+ _parent.AddInternal(index + 1, content);
}
/// <summary>
@@ -195,11 +179,8 @@ namespace Newtonsoft.Json.Linq
if (_parent == null)
throw new InvalidOperationException("The parent is missing.");
- JToken previous = Previous;
- if (previous == null)
- previous = _parent.Last;
-
- _parent.AddInternal(false, previous, content);
+ int index = _parent.IndexOfItem(this);
+ _parent.AddInternal(index, content);
}
/// <summary>
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj
index d3a8d9e..b996362 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj
@@ -96,8 +96,8 @@
<Compile Include="Converters\RegexConverter.cs" />
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
- <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\JPath.cs" />
+ <Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Linq\JRaw.cs" />
<Compile Include="Required.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj
index 7e590cc..f4b3f4b 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj
@@ -104,6 +104,7 @@
<Compile Include="Converters\StringEnumConverter.cs" />
<Compile Include="ConstructorHandling.cs" />
<Compile Include="JsonConstructorAttribute.cs" />
+ <Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Utilities\DynamicProxy.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JRaw.cs" />
@@ -115,7 +116,6 @@
<Compile Include="Serialization\JsonPrimitiveContract.cs" />
<Compile Include="Serialization\DynamicValueProvider.cs" />
<Compile Include="Serialization\ErrorEventArgs.cs" />
- <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
<Compile Include="PreserveReferencesHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
index 54f5f07..96815c0 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.Silverlight.csproj
@@ -127,7 +127,6 @@
<Compile Include="JsonValidatingReader.cs" />
<Compile Include="JsonWriter.cs" />
<Compile Include="JsonWriterException.cs" />
- <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\Extensions.cs" />
<Compile Include="Linq\IJEnumerable.cs" />
<Compile Include="Linq\JArray.cs" />
@@ -137,6 +136,7 @@
<Compile Include="Linq\JObject.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JProperty.cs" />
+ <Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Linq\JRaw.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj
index 0ef846e..766277d 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.WindowsPhone.csproj
@@ -100,7 +100,6 @@
<Compile Include="JsonValidatingReader.cs" />
<Compile Include="JsonWriter.cs" />
<Compile Include="JsonWriterException.cs" />
- <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
<Compile Include="Linq\Extensions.cs" />
<Compile Include="Linq\IJEnumerable.cs" />
<Compile Include="Linq\JArray.cs" />
@@ -110,6 +109,7 @@
<Compile Include="Linq\JObject.cs" />
<Compile Include="Linq\JPath.cs" />
<Compile Include="Linq\JProperty.cs" />
+ <Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Linq\JRaw.cs" />
<Compile Include="Linq\JToken.cs" />
<Compile Include="Linq\JTokenEqualityComparer.cs" />
diff --git a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
index 3f6d026..098ce15 100644
--- a/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
+++ b/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -114,7 +114,7 @@
<Compile Include="Serialization\JsonPrimitiveContract.cs" />
<Compile Include="Serialization\DynamicValueProvider.cs" />
<Compile Include="Serialization\ErrorEventArgs.cs" />
- <Compile Include="Linq\ComponentModel\JPropertyDescriptor.cs" />
+ <Compile Include="Linq\JPropertyDescriptor.cs" />
<Compile Include="Serialization\DefaultReferenceResolver.cs" />
<Compile Include="PreserveReferencesHandling.cs" />
<Compile Include="IJsonLineInfo.cs" />
@@ -262,5 +262,6 @@
<ItemGroup>
<EmbeddedResource Include="Dynamic.snk" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
index e37cbec..9712e8b 100644
--- a/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
+++ b/Src/Newtonsoft.Json/Properties/AssemblyInfo.cs
@@ -110,7 +110,7 @@ using System.Security;
// by using the '*' as shown below:
[assembly: AssemblyVersion("4.0.2.0")]
#if !PocketPC
-[assembly: AssemblyFileVersion("4.0.2.13722")]
+[assembly: AssemblyFileVersion("4.0.2.13728")]
#endif
[assembly: CLSCompliant(true)]
diff --git a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
index c4e3157..1068e13 100644
--- a/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
+++ b/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
@@ -124,7 +124,6 @@ namespace Newtonsoft.Json.Serialization
if (propertyInfo.IsVirtual())
{
Type currentType = propertyInfo.DeclaringType;
- Type[] types = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray();
while (result == null && currentType != null)
{
diff --git a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
index 7e20b0e..c34a8c7 100644
--- a/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
+++ b/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
@@ -631,5 +631,39 @@ namespace Newtonsoft.Json.Utilities
return -1;
}
+
+ /// <summary>
+ /// Returns the index of the first occurrence in a sequence by using the default equality comparer.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements of source.</typeparam>
+ /// <param name="list">A sequence in which to locate a value.</param>
+ /// <param name="value">The object to locate in the sequence</param>
+ /// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1.</returns>
+ public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value) where TSource : IEquatable<TSource>
+ {
+ return list.IndexOf<TSource>(value, EqualityComparer<TSource>.Default);
+ }
+
+ /// <summary>
+ /// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements of source.</typeparam>
+ /// <param name="list">A sequence in which to locate a value.</param>
+ /// <param name="value">The object to locate in the sequence</param>
+ /// <param name="comparer">An equality comparer to compare values.</param>
+ /// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1.</returns>
+ public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value, IEqualityComparer<TSource> comparer)
+ {
+ int index = 0;
+ foreach (TSource item in list)
+ {
+ if (comparer.Equals(item, value))
+ {
+ return index;
+ }
+ index++;
+ }
+ return -1;
+ }
}
} \ No newline at end of file