diff --git a/src/Debug/MetaAttributes/EcsMetaAttribute.cs b/src/Debug/MetaAttributes/EcsMetaAttribute.cs index 7b8e888..7cf48f4 100644 --- a/src/Debug/MetaAttributes/EcsMetaAttribute.cs +++ b/src/Debug/MetaAttributes/EcsMetaAttribute.cs @@ -3,4 +3,82 @@ namespace DCFApixels.DragonECS { public abstract class EcsMetaAttribute : Attribute { } + + + internal unsafe static class EcsMetaAttributeHalper + { + [ThreadStatic] + private static string[] _splitBuffer; + public static string[] Split(char separator, string value) + { + if(_splitBuffer == null) + { + _splitBuffer = new string[128]; + } + int length = value.Length; + int bufferIndex = 0; + fixed (char* ptr = value) + { + var reader = new SplitStream(ptr, value.Length, separator); + while (reader.Next()) + { + if (reader.current != null) + { + if(_splitBuffer.Length == bufferIndex) + { + Array.Resize(ref _splitBuffer, _splitBuffer.Length << 1); + } + _splitBuffer[bufferIndex++] = reader.current; + } + } + } + + string[] result = new string[bufferIndex]; + for (int i = 0; i < bufferIndex; i++) + { + result[i] = _splitBuffer[i]; + } + return result; + } + + #region SplitStream + private ref struct SplitStream + { + public string current; + public char* ptr; + public int length; + public readonly char separator; + public SplitStream(char* ptr, int length, char separator) + { + this.ptr = ptr; + this.length = length; + this.separator = separator; + current = null; + } + public bool Next() + { + if (length <= 0) { return false; } + char chr; + + char* spanPtr; + while (char.IsWhiteSpace(chr = *ptr) && length > 0) { ptr++; length--; } + spanPtr = ptr; + + char* spanEndPtr = spanPtr; + while ((chr = *ptr) != separator && length > 0) + { + ptr++; length--; + if (char.IsWhiteSpace(chr) == false) + { + spanEndPtr = ptr; + } + } + ptr++; length--; + + current = spanPtr < spanEndPtr ? new string(spanPtr, 0, (int)(spanEndPtr - spanPtr)) : null; + return true; + } + } + #endregion + } } diff --git a/src/Debug/MetaAttributes/MetaGroupAttribute.cs b/src/Debug/MetaAttributes/MetaGroupAttribute.cs index 4d8385b..b94f0b9 100644 --- a/src/Debug/MetaAttributes/MetaGroupAttribute.cs +++ b/src/Debug/MetaAttributes/MetaGroupAttribute.cs @@ -24,7 +24,6 @@ namespace DCFApixels.DragonECS { public static readonly MetaGroup Empty = new MetaGroup(""); private static string _pattern = @"Module(?=/)"; - private static char[] _separatpor = new char[] { '/' }; public readonly string Name; private string[] _path = null; @@ -34,7 +33,7 @@ namespace DCFApixels.DragonECS { if (_path == null) { - _path = Name.Split(_separatpor, StringSplitOptions.RemoveEmptyEntries); //TODO добавить ручное StringSplitOptions.TrimEntries + _path = EcsMetaAttributeHalper.Split('/', Name); } return _path; } diff --git a/src/Debug/MetaAttributes/MetaTagsAttribute.cs b/src/Debug/MetaAttributes/MetaTagsAttribute.cs index 35b9031..082c155 100644 --- a/src/Debug/MetaAttributes/MetaTagsAttribute.cs +++ b/src/Debug/MetaAttributes/MetaTagsAttribute.cs @@ -7,7 +7,6 @@ namespace DCFApixels.DragonECS public sealed class MetaTagsAttribute : EcsMetaAttribute { private readonly string[] _tags = Array.Empty(); - private static char[] _separatpor = new char[] { ',' }; public IReadOnlyList Tags { get { return _tags; } @@ -17,7 +16,7 @@ namespace DCFApixels.DragonECS public MetaTagsAttribute() { } public MetaTagsAttribute(string tags) { - _tags = tags.Split(_separatpor, StringSplitOptions.RemoveEmptyEntries); //TODO добавить ручное StringSplitOptions.TrimEntries + _tags = EcsMetaAttributeHalper.Split(',', tags); for (int i = 0; i < _tags.Length; i++) { _tags[i] = string.Intern(_tags[i]);