| File: System\Xml\StringHandle.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.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization; namespace System.Xml { internal enum StringHandleConstStringType { Type = 0, Root = 1, Item = 2 } internal sealed class StringHandle : IEquatable<StringHandle> { private readonly XmlBufferReader _bufferReader; private StringHandleType _type; private int _key; private int _offset; private int _length; private static readonly string[] s_constStrings = { "type", "root", "item" }; public StringHandle(XmlBufferReader bufferReader) { _bufferReader = bufferReader; SetValue(0, 0); } public void SetValue(int offset, int length) { _type = StringHandleType.UTF8; _offset = offset; _length = length; } public void SetConstantValue(StringHandleConstStringType constStringType) { _type = StringHandleType.ConstString; _key = (int)constStringType; } public void SetValue(int offset, int length, bool escaped) { _type = (escaped ? StringHandleType.EscapedUTF8 : StringHandleType.UTF8); _offset = offset; _length = length; } public void SetValue(int key) { _type = StringHandleType.Dictionary; _key = key; } public void SetValue(StringHandle value) { _type = value._type; _key = value._key; _offset = value._offset; _length = value._length; } public bool IsEmpty { get { if (_type == StringHandleType.UTF8) return _length == 0; return Equals2(string.Empty); } } public bool IsXmlns { get { if (_type == StringHandleType.UTF8) { if (_length != 5) return false; byte[] buffer = _bufferReader.Buffer; int offset = _offset; return buffer[offset + 0] == 'x' && buffer[offset + 1] == 'm' && buffer[offset + 2] == 'l' && buffer[offset + 3] == 'n' && buffer[offset + 4] == 's'; } return Equals2("xmlns"); } } public void ToPrefixHandle(PrefixHandle prefix) { Debug.Assert(_type == StringHandleType.UTF8); prefix.SetValue(_offset, _length); } public string GetString(XmlNameTable nameTable) { StringHandleType type = _type; if (type == StringHandleType.UTF8) return _bufferReader.GetString(_offset, _length, nameTable); if (type == StringHandleType.Dictionary) return nameTable.Add(_bufferReader.GetDictionaryString(_key).Value); if (type == StringHandleType.ConstString) return nameTable.Add(s_constStrings[_key]); // If none of the above, must be StringHandleType.EscapedUTF8 Debug.Assert(type == StringHandleType.EscapedUTF8, "Should be EscapedUTF8"); return _bufferReader.GetEscapedString(_offset, _length, nameTable); } public string GetString() { StringHandleType type = _type; if (type == StringHandleType.UTF8) return _bufferReader.GetString(_offset, _length); if (type == StringHandleType.Dictionary) return _bufferReader.GetDictionaryString(_key).Value; if (type == StringHandleType.ConstString) return s_constStrings[_key]; // If none of the above, must be StringHandleType.EscapedUTF8 Debug.Assert(type == StringHandleType.EscapedUTF8, "Should be EscapedUTF8"); return _bufferReader.GetEscapedString(_offset, _length); } public byte[] GetString(out int offset, out int length) { StringHandleType type = _type; if (type == StringHandleType.UTF8) { offset = _offset; length = _length; return _bufferReader.Buffer; } if (type == StringHandleType.Dictionary) { byte[] buffer = _bufferReader.GetDictionaryString(_key).ToUTF8(); offset = 0; length = buffer.Length; return buffer; } if (type == StringHandleType.ConstString) { byte[] buffer = XmlConverter.ToBytes(s_constStrings[_key]); offset = 0; length = buffer.Length; return buffer; } else { Debug.Assert(type == StringHandleType.EscapedUTF8); byte[] buffer = XmlConverter.ToBytes(_bufferReader.GetEscapedString(_offset, _length)); offset = 0; length = buffer.Length; return buffer; } } public bool TryGetDictionaryString([NotNullWhen(true)] out XmlDictionaryString? value) { if (_type == StringHandleType.Dictionary) { value = _bufferReader.GetDictionaryString(_key); return true; } else if (IsEmpty) { value = XmlDictionaryString.Empty; return true; } value = null; return false; } public override string ToString() { return GetString(); } private bool Equals2(int key2, XmlBufferReader bufferReader2) { StringHandleType type = _type; if (type == StringHandleType.Dictionary) return _bufferReader.Equals2(_key, key2, bufferReader2); if (type == StringHandleType.UTF8) return _bufferReader.Equals2(_offset, _length, bufferReader2.GetDictionaryString(key2).Value); Debug.Assert(type == StringHandleType.EscapedUTF8 || type == StringHandleType.ConstString); return GetString() == _bufferReader.GetDictionaryString(key2).Value; } private bool Equals2(XmlDictionaryString xmlString2) { StringHandleType type = _type; if (type == StringHandleType.Dictionary) return _bufferReader.Equals2(_key, xmlString2); if (type == StringHandleType.UTF8) return _bufferReader.Equals2(_offset, _length, xmlString2.ToUTF8()); Debug.Assert(type == StringHandleType.EscapedUTF8 || type == StringHandleType.ConstString); return GetString() == xmlString2.Value; } private bool Equals2(string s2) { StringHandleType type = _type; if (type == StringHandleType.Dictionary) return _bufferReader.GetDictionaryString(_key).Value == s2; if (type == StringHandleType.UTF8) return _bufferReader.Equals2(_offset, _length, s2); Debug.Assert(type == StringHandleType.EscapedUTF8 || type == StringHandleType.ConstString); return GetString() == s2; } private bool Equals2(int offset2, int length2, XmlBufferReader bufferReader2) { StringHandleType type = _type; if (type == StringHandleType.Dictionary) return bufferReader2.Equals2(offset2, length2, _bufferReader.GetDictionaryString(_key).Value); if (type == StringHandleType.UTF8) return _bufferReader.Equals2(_offset, _length, bufferReader2, offset2, length2); Debug.Assert(type == StringHandleType.EscapedUTF8 || type == StringHandleType.ConstString); return GetString() == _bufferReader.GetString(offset2, length2); } public bool Equals([NotNullWhen(true)] StringHandle? other) { if (other is null) return false; StringHandleType type = other._type; if (type == StringHandleType.Dictionary) return Equals2(other._key, other._bufferReader); if (type == StringHandleType.UTF8) return Equals2(other._offset, other._length, other._bufferReader); Debug.Assert(type == StringHandleType.EscapedUTF8 || type == StringHandleType.ConstString); return Equals2(other.GetString()); } public static bool operator ==(StringHandle s1, XmlDictionaryString xmlString2) { return s1.Equals2(xmlString2); } public static bool operator !=(StringHandle s1, XmlDictionaryString xmlString2) { return !s1.Equals2(xmlString2); } public static bool operator ==(StringHandle s1, string s2) { return s1.Equals2(s2); } public static bool operator !=(StringHandle s1, string s2) { return !s1.Equals2(s2); } public static bool operator ==(StringHandle s1, StringHandle s2) { return s1.Equals(s2); } public static bool operator !=(StringHandle s1, StringHandle s2) { return !s1.Equals(s2); } public int CompareTo(StringHandle that) { if (_type == StringHandleType.UTF8 && that._type == StringHandleType.UTF8) return _bufferReader.Compare(_offset, _length, that._offset, that._length); else return string.Compare(this.GetString(), that.GetString(), StringComparison.Ordinal); } public override bool Equals([NotNullWhen(true)] object? obj) { return Equals(obj as StringHandle); } public override int GetHashCode() { return GetString().GetHashCode(); } private enum StringHandleType { Dictionary, UTF8, EscapedUTF8, ConstString } } }