| File: System\Runtime\Serialization\ObjectReferenceStack.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.DataContractSerialization\src\System.Private.DataContractSerialization.csproj (System.Private.DataContractSerialization) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Xml; namespace System.Runtime.Serialization { internal struct ObjectReferenceStack { private const int MaximumArraySize = 16; private const int InitialArraySize = 4; private int _count; private object[]? _objectArray; private bool[]? _isReferenceArray; private Dictionary<object, object?>? _objectDictionary; internal void Push(object obj) { if (_objectArray == null) { _objectArray = new object[InitialArraySize]; _objectArray[_count++] = obj; } else if (_count < MaximumArraySize) { if (_count == _objectArray.Length) Array.Resize<object>(ref _objectArray, _objectArray.Length * 2); _objectArray[_count++] = obj; } else { _objectDictionary ??= new Dictionary<object, object?>(); _objectDictionary.Add(obj, null); _count++; } } internal void EnsureSetAsIsReference(object obj) { if (_count == 0) return; if (_count > MaximumArraySize) { if (_objectDictionary == null) { Debug.Fail("Object reference stack in invalid state"); } _objectDictionary.Remove(obj); } else { if ((_objectArray != null) && _objectArray[_count - 1] == obj) { if (_isReferenceArray == null) { _isReferenceArray = new bool[_objectArray.Length]; } else if (_count >= _isReferenceArray.Length) { Array.Resize<bool>(ref _isReferenceArray, _objectArray.Length); } _isReferenceArray[_count - 1] = true; } } } internal void Pop(object obj) { if (_count > MaximumArraySize) { if (_objectDictionary == null) { Debug.Fail("Object reference stack in invalid state"); } _objectDictionary.Remove(obj); } _count--; } internal bool Contains(object obj) { int currentCount = _count; if (currentCount > MaximumArraySize) { if (_objectDictionary != null && _objectDictionary.ContainsKey(obj)) return true; currentCount = MaximumArraySize; } for (int i = (currentCount - 1); i >= 0; i--) { if (object.ReferenceEquals(obj, _objectArray![i]) && _isReferenceArray != null && !_isReferenceArray[i]) return true; } return false; } } }