// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Text; namespace EpicGames.Core { /// /// Represents a memory region which can be treated as a utf-8 string. /// public class Utf8StringBuilder { readonly ArrayMemoryWriter _writer; /// /// Returns the length of this string /// public int Length { get => _writer.Length; set { int prevLength = _writer.Length; _writer.Resize(value); if (value > prevLength) { _writer.WrittenSpan.Slice(prevLength).Clear(); } } } /// /// Accessor for the written span /// public Span WrittenSpan => _writer.WrittenSpan; /// /// Accessor for the written memory /// public Memory WrittenMemory => _writer.WrittenMemory; /// /// Accessor for the written data /// public Utf8String WrittenString => new Utf8String(_writer.WrittenMemory); /// /// Constructor /// public Utf8StringBuilder() : this(256) { } /// /// Constructor /// public Utf8StringBuilder(int initialSize) : this(new ArrayMemoryWriter(initialSize)) { } /// /// Constructor /// public Utf8StringBuilder(ArrayMemoryWriter writer) { _writer = writer; } /// /// Append a character to the end of this builder /// /// Character to append public void Append(byte ch) { _writer.WriteUInt8(ch); } /// /// Append a character to the end of this builder /// /// Character to append public void Append(char ch) { if (ch < 127) { Append((byte)ch); } else { Append([ch]); } } /// /// Appends a string to the end of this builder /// /// Text to append public void Append(Utf8String text) { _writer.WriteFixedLengthBytes(text.Span); } /// /// Appends an integer to the end of this builder /// /// Value to append public void Append(int value) => Append((long)value); /// /// Appends an integer to the end of this builder /// /// Value to append public void Append(uint value) => Append((ulong)value); /// /// Appends an unsigned long to the end of this builder /// /// Value to append public void Append(long value) { if (value < 0) { _writer.WriteUInt8((byte)'-'); Append((ulong)-value); } else { Append((ulong)value); } } /// /// Appends an unsigned long to the end of this builder /// /// Value to append public void Append(ulong value) { Span span = _writer.GetSpan(32); int length = 0; for (ulong remaining = value; ; remaining /= 10) { ulong digit = remaining % 10U; span[length++] = (byte)('0' + digit); if (remaining == digit) { break; } } span.Slice(0, length).Reverse(); _writer.Advance(length); } /// /// Appends a string to the end of this builder /// /// Text to append public void Append(ReadOnlySpan text) { Span span = _writer.GetSpanAndAdvance(Encoding.UTF8.GetByteCount(text)); Encoding.UTF8.GetBytes(text, span); } /// /// Converts the written memory to a utf8 string /// /// public Utf8String ToUtf8String() { return new Utf8String(_writer.WrittenMemory); } /// public override string ToString() => ToUtf8String().ToString(); } }