Add IListTreeItem.ChildCount for optimization of ListTreeNode.Children

This commit is contained in:
ousttrue
2019-02-10 04:17:46 +09:00
parent 08ff5afae8
commit 1ca7c20f49
8 changed files with 112 additions and 38 deletions

View File

@@ -20,5 +20,7 @@ namespace UniJSON
public interface IListTreeItem
{
int ParentIndex { get; }
int ChildCount { get; }
void SetChildCount(int count);
}
}

View File

@@ -24,6 +24,7 @@ namespace UniJSON
T Key(Utf8String key, int parentIndex);
ValueNodeType ValueType { get; }
ArraySegment<Byte> Bytes { get; }
void SetBytesCount(int count);
Boolean GetBoolean();
String GetString();
Utf8String GetUtf8String();

View File

@@ -154,8 +154,7 @@ namespace UniJSON
// fix array range
var count = current.Bytes.Offset + 1 - segment.Bytes.Offset;
var arraySegment = segment.Subbytes(0, count);
array.SetValue(new JsonValue(arraySegment, ValueNodeType.Array, array.Value.ParentIndex));
array.SetValueBytesCount(count);
return array;
}
@@ -244,8 +243,7 @@ namespace UniJSON
// fix obj range
var count = current.Bytes.Offset + 1 - segment.Bytes.Offset;
var objSegment = segment.Subbytes(0, count);
obj.SetValue(new JsonValue(objSegment, ValueNodeType.Object, obj.Value.ParentIndex));
obj.SetValueBytesCount(count);
return obj;
}

View File

@@ -7,6 +7,10 @@ namespace UniJSON
{
public Utf8String Segment;
public ArraySegment<Byte> Bytes { get { return Segment.Bytes; } }
public void SetBytesCount(int count)
{
Segment = new Utf8String(new ArraySegment<byte>(Bytes.Array, Bytes.Offset, count));
}
public ValueNodeType ValueType
{
@@ -20,6 +24,16 @@ namespace UniJSON
private set;
}
int _childCount;
public int ChildCount
{
get { return _childCount; }
}
public void SetChildCount(int count)
{
_childCount = count;
}
public JsonValue(Utf8String segment, ValueNodeType valueType, int parentIndex) : this()
{
Segment = segment;

View File

@@ -303,10 +303,14 @@ namespace UniJSON
/// <summary>
/// This node index
/// </summary>
int _valueIndex;
public int ValueIndex
{
get;
private set;
get
{
if (m_Values == null) return -1;
return _valueIndex;
}
}
public ListTreeNode<T> Prev
@@ -334,14 +338,21 @@ namespace UniJSON
}
#region Children
public int ChildCount
{
get { return Value.ChildCount; }
}
public IEnumerable<ListTreeNode<T>> Children
{
get
{
for (int i = ValueIndex; i < m_Values.Count; ++i)
int count = 0;
for (int i = ValueIndex; count < ChildCount && i < m_Values.Count; ++i)
{
if (m_Values[i].ParentIndex == ValueIndex)
{
++count;
yield return new ListTreeNode<T>(m_Values, i);
}
}
@@ -372,7 +383,6 @@ namespace UniJSON
}
}
#endregion
public bool HasParent
{
get
@@ -399,27 +409,50 @@ namespace UniJSON
public ListTreeNode(List<T> values, int index = 0) : this()
{
m_Values = values;
ValueIndex = index;
_valueIndex = index;
}
#region JsonPointer
public void AddKey(Utf8String key)
public ListTreeNode<T> AddKey(Utf8String key)
{
m_Values.Add(default(T).Key(key, ValueIndex));
return AddValue(default(T).Key(key, ValueIndex));
}
public ListTreeNode<T> AddValue(ArraySegment<byte> bytes, ValueNodeType valueType)
{
return AddValue(default(T).New(bytes, valueType, ValueIndex));
}
public ListTreeNode<T> AddValue(T value)
{
if (m_Values == null)
{
// initialize empty tree
m_Values = new List<T>();
ValueIndex = -1;
_valueIndex = -1;
}
else
{
IncrementChildCount();
}
var index = m_Values.Count;
m_Values.Add(default(T).New(bytes, valueType, ValueIndex));
m_Values.Add(value);
return new ListTreeNode<T>(m_Values, index);
}
void IncrementChildCount()
{
var value = Value;
value.SetChildCount(value.ChildCount + 1);
SetValue(value);
}
public void SetValueBytesCount(int count)
{
var value = Value;
value.SetBytesCount(count);
SetValue(value);
}
#endregion
}
}

View File

@@ -357,65 +357,60 @@ namespace UniJSON
}
}
static ArraySegment<Byte> _Parse(ArraySegment<Byte> bytes, List<MsgPackValue> values, int parentIndex)
static ListTreeNode<MsgPackValue> _Parse(ListTreeNode<MsgPackValue> tree, ArraySegment<Byte> bytes)
{
MsgPackType formatType = GetFormat(bytes);
if (formatType.IsArray())
{
var index = values.Count;
var offset = bytes.Offset;
values.Add(new MsgPackValue(bytes, parentIndex));
var array = tree.AddValue(bytes, ValueNodeType.Array);
uint count;
bytes = GetItemCount(bytes, formatType, out count);
for (var i = 0; i < count; ++i)
{
bytes = _Parse(bytes, values, index);
var child = _Parse(array, bytes);
bytes = bytes.Advance(child.Value.Bytes.Count);
}
values[index] = new MsgPackValue(
new ArraySegment<byte>(bytes.Array,
offset, bytes.Offset - offset),
parentIndex);
array.SetValueBytesCount(bytes.Offset - array.Value.Bytes.Offset);
return array;
}
else if (formatType.IsMap())
{
var index = values.Count;
var offset = bytes.Offset;
values.Add(new MsgPackValue(bytes, parentIndex));
var obj = tree.AddValue(bytes, ValueNodeType.Object);
uint count;
bytes = GetItemCount(bytes, formatType, out count);
for (var i = 0; i < count; ++i)
{
// key
bytes = _Parse(bytes, values, index);
var key = _Parse(obj, bytes);
bytes = bytes.Advance(key.Value.Bytes.Count);
// value
bytes = _Parse(bytes, values, index);
var value = _Parse(obj, bytes);
bytes = bytes.Advance(value.Value.Bytes.Count);
}
values[index] = new MsgPackValue(
new ArraySegment<byte>(bytes.Array,
offset, bytes.Offset - offset),
parentIndex);
obj.SetValueBytesCount(bytes.Offset - obj.Value.Bytes.Offset);
return obj;
}
else
{
var body = GetBody(bytes, formatType);
var headerSize = body.Offset - bytes.Offset;
var size = headerSize + body.Count;
values.Add(new MsgPackValue(bytes.Take(size), parentIndex));
bytes = bytes.Advance(size);
var value = tree.AddValue(bytes.Take(size), ValueNodeType.Null);
return value;
}
return bytes;
}
public static ListTreeNode<MsgPackValue> Parse(ArraySegment<Byte> bytes)
{
var values = new List<MsgPackValue>();
_Parse(bytes, values, -1);
return new ListTreeNode<MsgPackValue>(values);
return _Parse(default(ListTreeNode<MsgPackValue>), bytes);
}
}
}

View File

@@ -16,6 +16,10 @@ namespace UniJSON
get;
private set;
}
public void SetBytesCount(int count)
{
Bytes = new ArraySegment<byte>(Bytes.Array, Bytes.Offset, count);
}
public MsgPackType Format
{
@@ -71,6 +75,16 @@ namespace UniJSON
}
}
int _childCount;
public int ChildCount
{
get { return _childCount; }
}
public void SetChildCount(int count)
{
_childCount = count;
}
public MsgPackValue(ArraySegment<Byte> segment, int parentIndex) : this()
{
Bytes = segment;
@@ -79,7 +93,7 @@ namespace UniJSON
public MsgPackValue New(ArraySegment<byte> bytes, ValueNodeType valueType, int parentIndex)
{
throw new NotImplementedException();
return new MsgPackValue(bytes, parentIndex);
}
public MsgPackValue Key(Utf8String key, int parentIndex)

View File

@@ -62,7 +62,24 @@ namespace UniJSON
}
Utf8String m_segment;
public ArraySegment<byte> Bytes { get { return m_segment.Bytes; } }
public void SetBytesCount(int count)
{
throw new NotImplementedException();
}
public int ChildCount
{
get
{
throw new NotImplementedException();
}
}
public void SetChildCount(int count)
{
throw new NotImplementedException();
}
public TomlValue(Utf8String segment, TomlValueType valueType, int parentIndex) : this()
{