qamp/Qrakhen.Qamp.Core/Values/Objects/String.cs

90 lines
2.4 KiB
C#

using Qrakhen.Qamp.Core.Collections;
using System.Text;
namespace Qrakhen.Qamp.Core.Values.Objects;
public class String(string? value) : Obj(ValueType.String)
{
private static readonly Register<uint, String> _strings = new();
public string? Value = value;
public override string ToString() => Value ?? "null";
public Value SubString(Value start, Value length)
{
if (Value == null)
throw new RuntimeException($"Can not call substring on an empty string.");
int index = start.IsInteger ?
(int)start.Signed :
throw new RuntimeException($"{nameof(String)}.{nameof(SubString)} requires first parameter 'start' to be an integer.");
if (index < 0 || index >= Value.Length)
throw new RuntimeException($"Parameter 'start' {start} was out of bounds.");
if (length.IsVoid)
return String.Make(Value.Substring(index));
int _length = length.IsInteger ?
(int)length.Signed :
throw new RuntimeException($"{nameof(String)}.{nameof(SubString)} requires second parameter 'length' to be an integer.");
return String.Make(Value.Substring(index, _length));
}
public Value IndexOf(Value needle)
{
if (!needle.IsString)
throw new RuntimeException($"Parameter 'needle' is expected to be of type string, got {needle} instead.");
return new Value(Value?.IndexOf(needle.Ptr.As<String>()!.Value!) ?? -1L);
}
public Value Split(Value delimiter)
{
return Values.Value.Void;
}
public Value Length()
{
return new Value(Value?.Length ?? 0L);
}
public uint GetHash()
{
if (string.IsNullOrEmpty(Value))
return 0;
return Value?.GetHash() ?? 0;
}
public static Value Make(string? value)
{
String? str;
var hash = value?.GetHash() ?? 0;
if (!_strings.TryGet(hash, out str)) {
str = new String(value);
_strings.Add(hash, str);
}
return Create(str);
}
public static byte[] SerializeStrings()
{
List<byte> result = new();
foreach (var pair in _strings) {
String str = pair.Value;
if (str == null || str.__GC_Marked)
continue;
byte[] bytes;
bytes = Encoding.ASCII.GetBytes(str.Value!);
result.AddRange(pair.Key.GetBytes());
result.AddRange(bytes.Length.GetBytes());
result.AddRange(bytes);
result.Add(0);
}
return result.ToArray();
}
}