| File: src\runtime\src\coreclr\tools\Common\Internal\Text\Utf8String.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// 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.Numerics; using System.Text; namespace Internal.Text { public readonly struct Utf8String : IEquatable<Utf8String>, IComparable<Utf8String> { private readonly byte[] _value; public bool IsNull => _value == null; public static readonly Utf8String Empty = new Utf8String([]); public Utf8String(byte[] underlyingArray) { _value = underlyingArray; } public Utf8String(ReadOnlySpan<byte> underlyingSpan) { _value = underlyingSpan.ToArray(); } public Utf8String(string s) { _value = Encoding.UTF8.GetBytes(s); } public static implicit operator Utf8Span(Utf8String s) => s._value; public int Length => _value.Length; public ReadOnlySpan<byte> AsSpan() => _value; public override string ToString() { return Encoding.UTF8.GetString(_value); } public override bool Equals(object obj) { return (obj is Utf8String utf8String) && Equals(utf8String); } public override unsafe int GetHashCode() { int length = _value.Length; uint hash = (uint)length; fixed (byte* ap = _value) { byte* a = ap; while (length >= 4) { hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *(uint*)a; a += 4; length -= 4; } if (length >= 2) { hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *(ushort*)a; a += 2; length -= 2; } if (length > 0) { hash = (hash + BitOperations.RotateLeft(hash, 5)) ^ *a; } hash += BitOperations.RotateLeft(hash, 7); hash += BitOperations.RotateLeft(hash, 15); return (int)hash; } } public bool Equals(Utf8String other) { return AsSpan().SequenceEqual(other.AsSpan()); } private static int Compare(Utf8String strA, Utf8String strB) { return strA.AsSpan().SequenceCompareTo(strB.AsSpan()); } public int CompareTo(Utf8String other) { return Compare(this, other); } public static Utf8String Concat(params ReadOnlySpan<Utf8String> strings) { int length = 0; foreach (Utf8String s in strings) length += s.Length; var result = new byte[length]; Span<byte> resultSpan = result; foreach (Utf8String s in strings) { s.AsSpan().CopyTo(resultSpan); resultSpan = resultSpan.Slice(s.Length); } return new Utf8String(result); } public static Utf8String Concat(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2) { var result = new byte[s1.Length + s2.Length]; s1.CopyTo(result); s2.CopyTo(result.AsSpan(s1.Length)); return new Utf8String(result); } public static Utf8String Concat(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2, ReadOnlySpan<byte> s3) { var result = new byte[s1.Length + s2.Length + s3.Length]; s1.CopyTo(result); s2.CopyTo(result.AsSpan(s1.Length)); s3.CopyTo(result.AsSpan(s1.Length + s2.Length)); return new Utf8String(result); } public static Utf8String Concat(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2, ReadOnlySpan<byte> s3, ReadOnlySpan<byte> s4) { var result = new byte[s1.Length + s2.Length + s3.Length + s4.Length]; s1.CopyTo(result); s2.CopyTo(result.AsSpan(s1.Length)); s3.CopyTo(result.AsSpan(s1.Length + s2.Length)); s4.CopyTo(result.AsSpan(s1.Length + s2.Length + s3.Length)); return new Utf8String(result); } public static Utf8String Concat(ReadOnlySpan<byte> s1, ReadOnlySpan<byte> s2, ReadOnlySpan<byte> s3, ReadOnlySpan<byte> s4, ReadOnlySpan<byte> s5) { var result = new byte[s1.Length + s2.Length + s3.Length + s4.Length + s5.Length]; s1.CopyTo(result); s2.CopyTo(result.AsSpan(s1.Length)); s3.CopyTo(result.AsSpan(s1.Length + s2.Length)); s4.CopyTo(result.AsSpan(s1.Length + s2.Length + s3.Length)); s5.CopyTo(result.AsSpan(s1.Length + s2.Length + s3.Length + s4.Length)); return new Utf8String(result); } } }