Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ion reader builder #46

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
251 changes: 251 additions & 0 deletions IonDotnet.Tests/Internals/TreeReaderTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
using IonDotnet.Builders;
using IonDotnet.Tests.Common;
using IonDotnet.Tree;
using IonDotnet.Tree.Impl;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using IonDotnet.Internals.Tree;
using System;
using System.Collections.Generic;
using System.Text;
using System.Numerics;
using System.Linq;

namespace IonDotnet.Tests.Internals
{
[TestClass]
public class TreeReaderTest
{

private IValueFactory _ionValueFactory = new ValueFactory();

[TestMethod]
public void SingleIntNumberTest()
{
var value = (IIonValue)_ionValueFactory.NewInt(123);
tgregg marked this conversation as resolved.
Show resolved Hide resolved
var reader = new UserTreeReader(value);

ReaderTestCommon.SingleNumber(reader, 123);
}

[TestMethod]
public void SingleDecimalNumberTest()
{
var decimalValue = new BigDecimal(decimal.MaxValue);
var value = (IIonValue)_ionValueFactory.NewDecimal(decimalValue);
var reader = new UserTreeReader(value);

Assert.AreEqual(IonType.Decimal, reader.MoveNext());
Assert.AreEqual(decimalValue, reader.DecimalValue());
}


[TestMethod]
public void SingleDoubleNumberTest()
{
var value = (IIonValue)_ionValueFactory.NewFloat(123.456);
var reader = new UserTreeReader(value);

Assert.AreEqual(IonType.Float, reader.MoveNext());
Assert.AreEqual(123.456, reader.DoubleValue());
}

[TestMethod]
public void TimestampTest()
{
var timestamp = new Timestamp(DateTime.Now);
var value = (IIonValue)_ionValueFactory.NewTimestamp(timestamp);
var reader = new UserTreeReader(value);

Assert.AreEqual(IonType.Timestamp, reader.MoveNext());
Assert.AreEqual(timestamp, reader.TimestampValue());
}

[TestMethod]
public void BoolValueTest()
{
var value = (IIonValue)_ionValueFactory.NewBool(true);
var reader = new UserTreeReader(value);

ReaderTestCommon.SingleBool(reader, true);
}

[TestMethod]
public void StringValueTest()
{
var value = (IIonValue)_ionValueFactory.NewString("test");
var reader = new UserTreeReader(value);

Assert.AreEqual(IonType.String, reader.MoveNext());
Assert.AreEqual("test", reader.StringValue());
}

[TestMethod]
public void NullValueTest()
{
var value = (IIonValue)_ionValueFactory.NewNull();
var reader = new UserTreeReader(value);

Assert.AreEqual(IonType.Null, reader.MoveNext());
Assert.IsTrue(reader.CurrentIsNull);
}

[TestMethod]
public void ListOfIntsTest()
{
//Must be: [123,456,789]
var value = (IIonValue)_ionValueFactory.NewEmptyList();
value.Add((IIonValue)_ionValueFactory.NewInt(123));
value.Add((IIonValue)_ionValueFactory.NewInt(456));
value.Add((IIonValue)_ionValueFactory.NewInt(789));
var reader = new UserTreeReader(value);

ReaderTestCommon.FlatIntList(reader);
}

[TestMethod]
public void SimpleDatagramTest()
{
//simple datagram: {yolo:true}
var value = new IonStruct{{ "yolo", (IIonValue)_ionValueFactory.NewBool(true) }};
var reader = new UserTreeReader(value);

ReaderTestCommon.OneBoolInStruct(reader);
}

[TestMethod]
public void FlatStructScalarTest()
{
//Must be a flat struct of scalar values:
//boolean:true
//str:"yes"
//integer:123456
//longInt:int.Max*2
//bigInt:long.Max*10
//double:2213.1267567f
var value = new IonStruct
{
{ "boolean", (IIonValue)_ionValueFactory.NewBool(true) },
{ "str", (IIonValue)_ionValueFactory.NewString("yes") },
{ "integer", (IIonValue)_ionValueFactory.NewInt(123456) },
{ "longInt", (IIonValue)_ionValueFactory.NewInt((long)int.MaxValue * 2) },
{ "bigInt", (IIonValue)_ionValueFactory.NewInt(BigInteger.Multiply(new BigInteger(long.MaxValue), 10)) },
{ "double", (IIonValue)_ionValueFactory.NewFloat(2213.1267567) }
};
var reader = new UserTreeReader(value);

ReaderTestCommon.FlatScalar(reader);
}

[TestMethod]
public void SingleSymbolTest()
{
//{single_symbol:'something'}
var value = new IonStruct {{ "single_symbol", (IIonValue)_ionValueFactory.NewSymbol("something")}};
var reader = new UserTreeReader(value);

ReaderTestCommon.SingleSymbol(reader);
}

[TestMethod]
public void NestedAndCombinedListStructTest()
{
//Must be:
// {
// menu: {
// id: "file",
// popup: [
// "Open",
// "Load",
// "Close"
// ],
// deep1: {
// deep2: {
// deep3: {
// deep4val: "enddeep"
// }
// }
// },
// positions: [
// 1234,
// 5678,
// 90
// ]
// }
// }

var popupList = (IIonValue)_ionValueFactory.NewEmptyList();
popupList.Add((IIonValue)_ionValueFactory.NewString("Open"));
popupList.Add((IIonValue)_ionValueFactory.NewString("Load"));
popupList.Add((IIonValue)_ionValueFactory.NewString("Close"));

var positionList = (IIonValue)_ionValueFactory.NewEmptyList();
positionList.Add((IIonValue)_ionValueFactory.NewInt(1234));
positionList.Add((IIonValue)_ionValueFactory.NewInt(5678));
positionList.Add((IIonValue)_ionValueFactory.NewInt(90));

var deep3 = new IonStruct {{ "deep4val", (IIonValue)_ionValueFactory.NewString("enddeep") }};

var deep2 = new IonStruct{{ "deep3", deep3 }};

var deep1 = new IonStruct { { "deep2", deep2 } };
tgregg marked this conversation as resolved.
Show resolved Hide resolved

var menu = new IonStruct
{
{ "id", (IIonValue)_ionValueFactory.NewString("file") },
{ "popup", popupList },
{ "deep1", deep1 },
{ "positions", positionList }
};

var value = new IonStruct {{ "menu", menu }};
var reader = new UserTreeReader(value);

ReaderTestCommon.Combined1(reader);
}

[TestMethod]
public void ValueWithAnnotationTest()
{
//Must be: {withannot: years::months::days::hours::minutes::seconds::18}
var intValue = (IIonValue)_ionValueFactory.NewInt(18);
intValue.AddTypeAnnotation("years");
intValue.AddTypeAnnotation("months");
intValue.AddTypeAnnotation("days");
intValue.AddTypeAnnotation("hours");
intValue.AddTypeAnnotation("minutes");
intValue.AddTypeAnnotation("seconds");
var value = new IonStruct { { "withannot", intValue } };
var reader = new UserTreeReader(value);

ReaderTestCommon.ReadAnnotations_SingleField(reader);
}

[TestMethod]
public void BlobTest()
{
//Must be in a struct:
// { blobbbb: {{data}} }
var arrayOfbytes = Enumerable.Repeat<byte>(1, 100).ToArray();
ReadOnlySpan<byte> bytes = new ReadOnlySpan<byte>(arrayOfbytes);
var blob = (IIonValue)_ionValueFactory.NewBlob(bytes);
var value = new IonStruct { { "blobbbb", blob }};
var reader = new UserTreeReader(value);

ReaderTestCommon.Struct_OneBlob(reader);
}

[TestMethod]
public void BlobPartialReadTest()
{
var blob = new byte[30];
for (var i = 0; i < 30; i++)
{
blob[i] = (byte)i;
}
var value = (IIonValue)_ionValueFactory.NewBlob(blob);
var reader = new UserTreeReader(value);

ReaderTestCommon.Blob_PartialRead(30, 7, reader);
}
}
}
47 changes: 20 additions & 27 deletions IonDotnet/Internals/Tree/SystemTreeReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ internal class SystemTreeReader : IIonReader
protected IIonValue _current;
protected bool _eof;
protected int _top;
// Holds pairs: IonValue parent (_parent), Iterator<IIonValue> cursor (_iter)
private Object[] _stack = new Object[10];
tgregg marked this conversation as resolved.
Show resolved Hide resolved
private int pos = 0;

protected SystemTreeReader(IIonValue value)
{
Expand All @@ -34,7 +36,7 @@ protected SystemTreeReader(IIonValue value)
else
{
_parent = (IIonValue)value.Container;
_current = value;
_next = value;
}
}

Expand Down Expand Up @@ -80,13 +82,15 @@ public int GetBytes(Span<byte> buffer)
else if (lobSize <= bufSize)
{
_current.Bytes().CopyTo(buffer);
pos += lobSize;
return lobSize;
}
else if (lobSize > bufSize)
else if (lobSize > bufSize && pos <= lobSize)
{
_current.Bytes()
.Slice(0, bufSize - 1)
.Slice(pos, bufSize)
.CopyTo(buffer);
pos += bufSize;
return bufSize;
}

Expand Down Expand Up @@ -130,7 +134,7 @@ public virtual IonType MoveNext()
if (_next == null && !HasNext())
{
_current = null;
return IonType.Null;
return IonType.None;
}
_current = _next;
_next = null;
Expand Down Expand Up @@ -196,22 +200,22 @@ private void Pop()
public virtual bool HasNext()
{
IonType next_type = NextHelperSystem();
tgregg marked this conversation as resolved.
Show resolved Hide resolved
return (next_type != IonType.Null);
return (next_type != IonType.None);
}

protected IonType NextHelperSystem()
{
if (_eof) return IonType.Null;
if (_eof) return IonType.None;
if (_next != null) return _next.Type();

while(_iter != null && _iter.MoveNext())
if(_iter != null && _iter.MoveNext())
{
_next = _iter.Current;
}

if ((_eof = (_next == null)))
{
return IonType.Null;
return IonType.None;
}
return _next.Type();
}
Expand Down Expand Up @@ -244,14 +248,14 @@ public Timestamp TimestampValue()
internal class Children : IEnumerator<IIonValue>
{
bool _eof;
int _next_idx;
int _nextIdx;
IIonValue _parent;
IIonValue _curr;

public Children(IIonValue parent)
{
_parent = parent;
_next_idx = 0;
_nextIdx = -1;
_curr = null;
if (_parent.IsNull)
{
Expand All @@ -266,7 +270,7 @@ public IIonValue Current
{
try
{
return _parent.GetElementAt(_next_idx);
return _parent.GetElementAt(_nextIdx);
}
catch (IndexOutOfRangeException)
{
Expand All @@ -286,28 +290,17 @@ public bool MoveNext()
{
if (_eof)
{
_curr = null;
return false;
}

int len = _parent.Count;

if (_next_idx > 0)
if (_nextIdx >= _parent.Count - 1)
{
int ii = _next_idx - 1;
_next_idx = len;

while (ii < len)
{
if (_curr == _parent.GetElementAt(ii))
{
_next_idx = ii + 1;
break;
}
}
_eof = true;
}
if (_next_idx >= _parent.Count)
else
{
_eof = true;
_curr = _parent.GetElementAt(++_nextIdx);
}
return !_eof;
}
Expand Down
Loading