// 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();
}
}