-/* https://github.com/mbuchetics/RangeTree よりコピペ。このファイルのみMITライセンスに従います */\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Threading.Tasks;\r
-\r
-namespace FooEditEngine\r
-{\r
- /// <summary>\r
- /// マーカーを表す\r
- /// </summary>\r
- internal interface IRange\r
- {\r
- /// <summary>\r
- /// マーカーの開始位置。-1を設定した場合、そのマーカーはレタリングされません\r
- /// </summary>\r
- int start { get; set; }\r
- /// <summary>\r
- /// マーカーの長さ。0を設定した場合、そのマーカーはレタリングされません\r
- /// </summary>\r
- int length { get; set; }\r
- }\r
-\r
- internal sealed class RangeCollection<T> : IEnumerable<T>\r
- where T : IRange\r
- {\r
- List<T> collection;\r
-\r
- public RangeCollection()\r
- : this(null)\r
- {\r
- }\r
-\r
- public RangeCollection(IEnumerable<T> collection)\r
- {\r
- if (collection == null)\r
- this.collection = new List<T>();\r
- else\r
- this.collection = new List<T>(collection);\r
- }\r
-\r
- public T this[int i]\r
- {\r
- get\r
- {\r
- return this.collection[i];\r
- }\r
- set\r
- {\r
- this.collection[i] = value;\r
- }\r
- }\r
-\r
- public int Count\r
- {\r
- get\r
- {\r
- return this.collection.Count;\r
- }\r
- }\r
-\r
- public void Add(T item)\r
- {\r
- this.collection.Add(item);\r
- for (int i = this.collection.Count - 1; i >= 0; i--)\r
- {\r
- if (i > 0 && this.collection[i].start < this.collection[i - 1].start)\r
- {\r
- T temp = this.collection[i];\r
- this.collection[i] = this.collection[i - 1];\r
- this.collection[i - 1] = temp;\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- public void Remove(int start, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
-\r
- int at = this.IndexOf(start);\r
-\r
- int endAt = this.IndexOf(start + length - 1);\r
-\r
- if(at != -1 && endAt != -1)\r
- {\r
- for (int i = endAt; i >= at; i--)\r
- {\r
- this.collection.RemoveAt(i);\r
- }\r
- }\r
- else if (at != -1)\r
- {\r
- this.collection.RemoveAt(at);\r
- }\r
- else if(endAt != -1)\r
- {\r
- this.collection.RemoveAt(endAt);\r
- }\r
- }\r
-\r
- public void RemoveNearest(int start, int length)\r
- {\r
- if (this.collection.Count == 0)\r
- return;\r
- \r
- int nearAt;\r
- int at = this.IndexOfNearest(start, out nearAt);\r
- if (at == -1)\r
- at = nearAt;\r
- \r
- int nearEndAt;\r
- int endAt = this.IndexOfNearest(start + length - 1, out nearEndAt);\r
- if (endAt == -1)\r
- endAt = nearEndAt;\r
- \r
- int end = start + length - 1; \r
- for (int i = endAt; i >= at; i--)\r
- {\r
- int markerEnd = this.collection[i].start + this.collection[i].length - 1;\r
- if (this.collection[i].start >= start && markerEnd <= end ||\r
- markerEnd >= start && markerEnd <= end ||\r
- this.collection[i].start >= start && this.collection[i].start <= end ||\r
- this.collection[i].start < start && markerEnd > end)\r
- this.collection.RemoveAt(i);\r
- }\r
- }\r
-\r
- public void RemoveAt(int index)\r
- {\r
- this.collection.RemoveAt(index);\r
- }\r
-\r
- public int IndexOf(int start)\r
- {\r
- int dummy;\r
- return this.IndexOfNearest(start, out dummy);\r
- }\r
-\r
- int IndexOfNearest(int start,out int nearIndex)\r
- {\r
- nearIndex = -1;\r
- int left = 0, right = this.collection.Count - 1, mid;\r
- while (left <= right)\r
- {\r
- mid = (left + right) / 2;\r
- T item = this.collection[mid];\r
- if (start >= item.start && start < item.start + item.length)\r
- {\r
- return mid;\r
- }\r
- if (start < item.start)\r
- {\r
- right = mid - 1;\r
- }\r
- else\r
- {\r
- left = mid + 1;\r
- }\r
- }\r
- System.Diagnostics.Debug.Assert(left >= 0 || right >= 0);\r
- nearIndex = left >= 0 ? left : right;\r
- if (nearIndex > this.collection.Count - 1)\r
- nearIndex = right;\r
- return -1;\r
- }\r
-\r
- public IEnumerable<T> Get(int index)\r
- {\r
- int at = this.IndexOf(index);\r
- if (at == -1)\r
- yield break;\r
- yield return this.collection[at];\r
- }\r
-\r
- public IEnumerable<T> Get(int start, int length)\r
- {\r
- int nearAt;\r
- int at = this.IndexOfNearest(start,out nearAt);\r
- if (at == -1)\r
- at = nearAt;\r
-\r
- if (at == -1)\r
- yield break;\r
-\r
- int end = start + length - 1;\r
- for (int i = at; i < this.collection.Count; i++)\r
- {\r
- int markerEnd = this.collection[i].start + this.collection[i].length - 1;\r
- if (this.collection[i].start >= start && markerEnd <= end ||\r
- markerEnd >= start && markerEnd <= end ||\r
- this.collection[i].start >= start && this.collection[i].start <= end ||\r
- this.collection[i].start < start && markerEnd > end)\r
- yield return this.collection[i];\r
- else if (this.collection[i].start > start + length)\r
- yield break;\r
- }\r
- }\r
-\r
- public void Clear()\r
- {\r
- this.collection.Clear();\r
- }\r
-\r
- public IEnumerator<T> GetEnumerator()\r
- {\r
- foreach (T item in this.collection)\r
- yield return item;\r
- }\r
-\r
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()\r
- {\r
- throw new NotImplementedException();\r
- }\r
- }\r
-\r
-}\r
+/* https://github.com/mbuchetics/RangeTree よりコピペ。このファイルのみMITライセンスに従います */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FooEditEngine
+{
+ /// <summary>
+ /// マーカーを表す
+ /// </summary>
+ internal interface IRange
+ {
+ /// <summary>
+ /// マーカーの開始位置。-1を設定した場合、そのマーカーはレタリングされません
+ /// </summary>
+ int start { get; set; }
+ /// <summary>
+ /// マーカーの長さ。0を設定した場合、そのマーカーはレタリングされません
+ /// </summary>
+ int length { get; set; }
+ }
+
+ internal sealed class RangeCollection<T> : IEnumerable<T>
+ where T : IRange
+ {
+ List<T> collection;
+
+ public RangeCollection()
+ : this(null)
+ {
+ }
+
+ public RangeCollection(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ this.collection = new List<T>();
+ else
+ this.collection = new List<T>(collection);
+ }
+
+ public T this[int i]
+ {
+ get
+ {
+ return this.collection[i];
+ }
+ set
+ {
+ this.collection[i] = value;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return this.collection.Count;
+ }
+ }
+
+ public void Add(T item)
+ {
+ this.collection.Add(item);
+ for (int i = this.collection.Count - 1; i >= 0; i--)
+ {
+ if (i > 0 && this.collection[i].start < this.collection[i - 1].start)
+ {
+ T temp = this.collection[i];
+ this.collection[i] = this.collection[i - 1];
+ this.collection[i - 1] = temp;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ public void Remove(int start, int length)
+ {
+ if (this.collection.Count == 0)
+ return;
+
+ int at = this.IndexOf(start);
+
+ int endAt = this.IndexOf(start + length - 1);
+
+ if(at != -1 && endAt != -1)
+ {
+ for (int i = endAt; i >= at; i--)
+ {
+ this.collection.RemoveAt(i);
+ }
+ }
+ else if (at != -1)
+ {
+ this.collection.RemoveAt(at);
+ }
+ else if(endAt != -1)
+ {
+ this.collection.RemoveAt(endAt);
+ }
+ }
+
+ public void RemoveNearest(int start, int length)
+ {
+ if (this.collection.Count == 0)
+ return;
+
+ int nearAt;
+ int at = this.IndexOfNearest(start, out nearAt);
+ if (at == -1)
+ at = nearAt;
+
+ int nearEndAt;
+ int endAt = this.IndexOfNearest(start + length - 1, out nearEndAt);
+ if (endAt == -1)
+ endAt = nearEndAt;
+
+ int end = start + length - 1;
+ for (int i = endAt; i >= at; i--)
+ {
+ int markerEnd = this.collection[i].start + this.collection[i].length - 1;
+ if (this.collection[i].start >= start && markerEnd <= end ||
+ markerEnd >= start && markerEnd <= end ||
+ this.collection[i].start >= start && this.collection[i].start <= end ||
+ this.collection[i].start < start && markerEnd > end)
+ this.collection.RemoveAt(i);
+ }
+ }
+
+ public void RemoveAt(int index)
+ {
+ this.collection.RemoveAt(index);
+ }
+
+ public int IndexOf(int start)
+ {
+ int dummy;
+ return this.IndexOfNearest(start, out dummy);
+ }
+
+ int IndexOfNearest(int start,out int nearIndex)
+ {
+ nearIndex = -1;
+ int left = 0, right = this.collection.Count - 1, mid;
+ while (left <= right)
+ {
+ mid = (left + right) / 2;
+ T item = this.collection[mid];
+ if (start >= item.start && start < item.start + item.length)
+ {
+ return mid;
+ }
+ if (start < item.start)
+ {
+ right = mid - 1;
+ }
+ else
+ {
+ left = mid + 1;
+ }
+ }
+ System.Diagnostics.Debug.Assert(left >= 0 || right >= 0);
+ nearIndex = left >= 0 ? left : right;
+ if (nearIndex > this.collection.Count - 1)
+ nearIndex = right;
+ return -1;
+ }
+
+ public IEnumerable<T> Get(int index)
+ {
+ int at = this.IndexOf(index);
+ if (at == -1)
+ yield break;
+ yield return this.collection[at];
+ }
+
+ public IEnumerable<T> Get(int start, int length)
+ {
+ int nearAt;
+ int at = this.IndexOfNearest(start,out nearAt);
+ if (at == -1)
+ at = nearAt;
+
+ if (at == -1)
+ yield break;
+
+ int end = start + length - 1;
+ for (int i = at; i < this.collection.Count; i++)
+ {
+ int markerEnd = this.collection[i].start + this.collection[i].length - 1;
+ if (this.collection[i].start >= start && markerEnd <= end ||
+ markerEnd >= start && markerEnd <= end ||
+ this.collection[i].start >= start && this.collection[i].start <= end ||
+ this.collection[i].start < start && markerEnd > end)
+ yield return this.collection[i];
+ else if (this.collection[i].start > start + length)
+ yield break;
+ }
+ }
+
+ public void Clear()
+ {
+ this.collection.Clear();
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ foreach (T item in this.collection)
+ yield return item;
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+}