Added EBofaType enum
This commit is contained in:
parent
ae2ff31f21
commit
90e19222e7
13 changed files with 11 additions and 904 deletions
|
@ -1,13 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
struct BofaAbleAttribute : Attribute
|
|
||||||
{
|
|
||||||
public StringView Name;
|
|
||||||
|
|
||||||
public this(StringView pName)
|
|
||||||
{
|
|
||||||
Name = pName;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
[AttributeUsage(.Field)]
|
|
||||||
struct BofaObjectAttribute : Attribute, IOnTypeInit
|
|
||||||
{
|
|
||||||
public StringView Name;
|
|
||||||
|
|
||||||
public this(StringView pName)
|
|
||||||
{
|
|
||||||
Name = pName;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Comptime]
|
|
||||||
public void OnTypeInit(Type type, Self* prev)
|
|
||||||
{
|
|
||||||
Compiler.EmitTypeBody(type, "public override void ToString(String str)\n{\n");
|
|
||||||
for (var fieldInfo in type.GetFields())
|
|
||||||
{
|
|
||||||
if (!fieldInfo.IsInstanceField)
|
|
||||||
continue;
|
|
||||||
if (@fieldInfo.Index > 0)
|
|
||||||
Compiler.EmitTypeBody(type, "\tstr.Append(\", \");\n");
|
|
||||||
Compiler.EmitTypeBody(type, scope $"\tstr.AppendF($\"{fieldInfo.Name}={{ {fieldInfo.Name} }}\");\n");
|
|
||||||
}
|
|
||||||
Compiler.EmitTypeBody(type, "}");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,233 +0,0 @@
|
||||||
namespace Bofa.Builder;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
typealias bb = BofaBuilder;
|
|
||||||
class BofaBuilder
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Allows users to easily build a bofa file via code
|
|
||||||
name, typename, typeindicator, value
|
|
||||||
|
|
||||||
This is really fucking slow, because we are allocating so much
|
|
||||||
In a sensible application you wouldnd call this all that much anyways, so I dont care
|
|
||||||
*/
|
|
||||||
public struct b
|
|
||||||
{
|
|
||||||
public String Name; //This is always dynamic
|
|
||||||
public String Type; //Never dynamic
|
|
||||||
public String TypeName; //Only dynamic on custom types
|
|
||||||
public String Value; //Dynamic on everything that isnt a array or object
|
|
||||||
public Span<b> Members;
|
|
||||||
|
|
||||||
public this(String name, String type, String typeName, String value, Span<b> members)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
Type = type;
|
|
||||||
TypeName = typeName;
|
|
||||||
Value = value;
|
|
||||||
Members = members;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Cleanup()
|
|
||||||
{
|
|
||||||
delete Name;
|
|
||||||
if(Type == "c")
|
|
||||||
delete TypeName;
|
|
||||||
|
|
||||||
if(Type != "a" && Type != "o")
|
|
||||||
delete Value;
|
|
||||||
|
|
||||||
for(let e in Members)
|
|
||||||
{
|
|
||||||
e.Cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ToString(String toAppend, uint32 depth)
|
|
||||||
{
|
|
||||||
String toAdd = scope .(scope $"{Type} ");
|
|
||||||
toAdd.PadLeft(depth+toAdd.Length,' ');
|
|
||||||
if(Type == "c")
|
|
||||||
toAdd.Append(scope $"{TypeName} ");
|
|
||||||
toAdd.Append(scope $"{Name} ");
|
|
||||||
//Every single
|
|
||||||
if(Type != "a" && Type != "o") //In this case we can just normally return
|
|
||||||
{
|
|
||||||
|
|
||||||
if(Type != "t")
|
|
||||||
toAdd.Append(scope $"{Value}");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var en = Value.Split('\n');
|
|
||||||
toAdd.Append(en.GetNext());
|
|
||||||
|
|
||||||
for(var e in en)
|
|
||||||
{
|
|
||||||
toAdd.Append('\n');
|
|
||||||
String n = scope .();
|
|
||||||
n.PadLeft(depth+1, ' ');
|
|
||||||
n.Append("- ");
|
|
||||||
n.Append(e);
|
|
||||||
toAdd.Append(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
toAdd.Append('\n');
|
|
||||||
if(Type == "a" || Type == "o")
|
|
||||||
{
|
|
||||||
for(var b in Members)
|
|
||||||
{
|
|
||||||
b.ToString(toAdd,depth+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toAppend.Append(toAdd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Span<b> values;
|
|
||||||
private List<b> valueList = new .();
|
|
||||||
public this(params Span<b> input)
|
|
||||||
{
|
|
||||||
values = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ~this()
|
|
||||||
{
|
|
||||||
for(var a in values)
|
|
||||||
a.Cleanup();
|
|
||||||
|
|
||||||
for(var a in valueList)
|
|
||||||
a.Cleanup();
|
|
||||||
delete valueList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ToString(String strBuffer)
|
|
||||||
{
|
|
||||||
for(var a in values)
|
|
||||||
{
|
|
||||||
a.ToString(strBuffer, 0);
|
|
||||||
}
|
|
||||||
for(var a in valueList)
|
|
||||||
{
|
|
||||||
a.ToString(strBuffer, 0);
|
|
||||||
}
|
|
||||||
if(strBuffer[strBuffer.Length-1] == '\n')
|
|
||||||
strBuffer.RemoveFromEnd(1); //There are probably better ways to do this but I dont care
|
|
||||||
}
|
|
||||||
|
|
||||||
///Adds a single entry after the creation
|
|
||||||
public void Add(b pToAdd)
|
|
||||||
{
|
|
||||||
valueList.Add(pToAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Num(StringView name, float number)
|
|
||||||
{
|
|
||||||
return .(new .(name), "n", null, new .(number.ToString(.. scope .())),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Bool(StringView name, bool bool)
|
|
||||||
{
|
|
||||||
return .(new .(name), "b", null, new .(bool.ToString(.. scope .())),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Line(StringView name, StringView line)
|
|
||||||
{
|
|
||||||
return .(new .(name), "l", null, new .(line),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b BigNum(StringView name, double bigNum)
|
|
||||||
{
|
|
||||||
return .(new .(name), "bn", null, new .(bigNum.ToString(.. scope .())),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Int(StringView name, int32 number)
|
|
||||||
{
|
|
||||||
return .(new .(name), "i", null, new .(number.ToString(.. scope .())),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b BigInt(StringView name, int64 number)
|
|
||||||
{
|
|
||||||
return .(new .(name), "bi", null, new .(number.ToString(.. scope .())),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Text(StringView name, StringView text)
|
|
||||||
{
|
|
||||||
return .(new .(name),"t", null, new .(text),null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Custom(StringView name, StringView type, StringView value)
|
|
||||||
{
|
|
||||||
return .(new .(name), "c",new .(type), new .(value), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Object(StringView name, params Span<b> input)
|
|
||||||
{
|
|
||||||
return .(new .(name), "o", null,null,input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static b Array(StringView name, params Span<b> input)
|
|
||||||
{
|
|
||||||
return .(new .(name), "a", null,new .(""),input);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Array functions, that dont take a name
|
|
||||||
public static b NumA(float value)
|
|
||||||
{
|
|
||||||
return Num("-", value);
|
|
||||||
}
|
|
||||||
public static b BoolA(bool value)
|
|
||||||
{
|
|
||||||
return Bool("-", value);
|
|
||||||
}
|
|
||||||
public static b LineA(StringView value)
|
|
||||||
{
|
|
||||||
return Line("-", value);
|
|
||||||
}
|
|
||||||
public static b BigNumA(double value)
|
|
||||||
{
|
|
||||||
return BigNum("-", value);
|
|
||||||
}
|
|
||||||
public static b IntA(int32 value)
|
|
||||||
{
|
|
||||||
return Int("-", value);
|
|
||||||
}
|
|
||||||
public static b BigIntA(int64 value)
|
|
||||||
{
|
|
||||||
return BigInt("-", value);
|
|
||||||
}
|
|
||||||
public static b TextA(StringView value)
|
|
||||||
{
|
|
||||||
return Text("-", value);
|
|
||||||
}
|
|
||||||
public static b CustomA(StringView type, StringView value)
|
|
||||||
{
|
|
||||||
return Custom("-", type, value);
|
|
||||||
}
|
|
||||||
public static b ObjectA(params Span<b> input)
|
|
||||||
{
|
|
||||||
return .("-", "o", null, null, input);
|
|
||||||
}
|
|
||||||
public static b ArrayA(params Span<b> input)
|
|
||||||
{
|
|
||||||
return .("-", "a", null, null, input);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public static void Test()
|
|
||||||
{
|
|
||||||
BofaBuilder builder = scope .(
|
|
||||||
bb.Num("Number",123),
|
|
||||||
bb.Custom("farbe", "color", "255 0 255"),
|
|
||||||
bb.Text("Text", "multi \nLine"),
|
|
||||||
bb.Object( "obj",
|
|
||||||
bb.Num("SubObject", 123)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
Console.WriteLine(builder.ToString(.. scope .()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
class BofaReflector
|
|
||||||
{
|
|
||||||
|
|
||||||
///Parse an object into its bofa representation
|
|
||||||
public static void ToBofa<T>(T pInput, Bofa buffer)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Recursivly loop through all fields of the object and parse all marked fields
|
|
||||||
if a custom parser is supplied via IBofaParseable we use that.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//User supplied their own parser
|
|
||||||
if(let iface = pInput as IBofaParseable)
|
|
||||||
{
|
|
||||||
//Simply just call the user supplied parser
|
|
||||||
iface.ToBofa(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.Type = .Object;
|
|
||||||
buffer.TypeName = "Object";
|
|
||||||
buffer.Value.Object = new .();
|
|
||||||
|
|
||||||
var fields = typeof(T).GetFields();
|
|
||||||
for(var i in fields) //Loop through all fields of the object
|
|
||||||
{
|
|
||||||
//If we should actually parse the field
|
|
||||||
if(i.GetCustomAttribute<BofaAbleAttribute>() case .Ok(let attr))
|
|
||||||
{
|
|
||||||
if(i.GetValue(pInput) case .Ok(let value))
|
|
||||||
{
|
|
||||||
|
|
||||||
Bofa fieldContent = new .();
|
|
||||||
fieldContent.Name = attr.Name;
|
|
||||||
Compiler.Mixin(scope $"ToBofa<{i.GetType()}>(value,fieldContent);");
|
|
||||||
//ToBofa<typeof(value)>(value, fieldContent);
|
|
||||||
buffer.Value.Object.Add(fieldContent.Name, fieldContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
class BofaResult
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
BofaResult contains the result of an interaction with the Bofa Parser Library
|
|
||||||
If you parse a String the parser will return a BofaResult Object
|
|
||||||
Querying an existing Bofa Result will also return a sub BofaResult
|
|
||||||
This exist in order to keep the bofa data objects clean and instead manage access via this class
|
|
||||||
It also contains information about wether any one query was sucessfull
|
|
||||||
*/
|
|
||||||
private bool _isResult = false; //If this is true we dont delete any actual object data
|
|
||||||
private String _data = null; //The backing data, needs to be cleared on destruction if set
|
|
||||||
private Dictionary<StringView, Bofa> _contents = new Dictionary<StringView, Bofa>(10); //Storage
|
|
||||||
private List<Bofa> _result = null;
|
|
||||||
private Bofa _lastObject = null; //Keeps track of the last object we have added
|
|
||||||
|
|
||||||
|
|
||||||
public bool OK { //Keeps track of wether the parsing failed at some point
|
|
||||||
public get;
|
|
||||||
private set;
|
|
||||||
} = true;
|
|
||||||
|
|
||||||
public ~this()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(_result != null)
|
|
||||||
delete _result;
|
|
||||||
|
|
||||||
if(_data != null)
|
|
||||||
{
|
|
||||||
delete _data;
|
|
||||||
for(let i in _contents)
|
|
||||||
{
|
|
||||||
delete i.value;
|
|
||||||
}
|
|
||||||
} //We only delete values on the core object in order to not have error with dumb shit
|
|
||||||
|
|
||||||
delete _contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Insert(BofaParser.lineParserResult pResult)
|
|
||||||
{ //This is guaranteed to be a valid pResult, because no one would ever call this from somewhere else with different params
|
|
||||||
//DONT DO THIS ^
|
|
||||||
|
|
||||||
if(pResult.Bofa.0 > 0 && (_lastObject == null || (_lastObject.Type != .Object && _lastObject.Type != .Array && _lastObject.Type != .Text)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(pResult.Bofa.0 > 0)
|
|
||||||
if(pResult.IsBofa)
|
|
||||||
return _lastObject.[Friend]Insert(pResult.Bofa.0-1, pResult.Bofa.1);
|
|
||||||
else
|
|
||||||
return _lastObject.[Friend]Insert(pResult.Text.0-1, null, pResult.Text.1);
|
|
||||||
//Okay so we really need to add it in on this layer
|
|
||||||
|
|
||||||
if(!pResult.IsBofa)
|
|
||||||
{ //For text entries on the current layer
|
|
||||||
if(_lastObject.Type != .Text)
|
|
||||||
return false;
|
|
||||||
_lastObject.Value.Text.Append(scope $"\n{pResult.Text.1}");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let toAdd = pResult.Bofa.1;
|
|
||||||
if(_contents.ContainsKey(toAdd.Name))
|
|
||||||
return false; //Dublicate name error
|
|
||||||
_contents.Add(toAdd.Name, toAdd);
|
|
||||||
_lastObject = toAdd;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Interface functions go here
|
|
||||||
public Result<Bofa> this[StringView pValue]
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
if(!_contents.ContainsKey(pValue))
|
|
||||||
return .Err;
|
|
||||||
return _contents[pValue];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<Bofa> GetByName(StringView pValue)
|
|
||||||
{
|
|
||||||
return this[pValue];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
[Union]
|
|
||||||
struct BofaValue
|
|
||||||
{
|
|
||||||
public float Number;
|
|
||||||
public double BigNumber;
|
|
||||||
public int32 Integer;
|
|
||||||
public int64 BigInteger;
|
|
||||||
public bool Boolean;
|
|
||||||
public StringView Line;
|
|
||||||
public StringView Custom;
|
|
||||||
public String Text;
|
|
||||||
public Dictionary<StringView, Bofa> Object = null;
|
|
||||||
public List<Bofa> Array = null;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
|
|
||||||
interface IBofaParseable
|
|
||||||
{
|
|
||||||
public void ToBofa(Bofa target);
|
|
||||||
public void FromBofa(Bofa input);
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Bofa.Testing.Parsing;
|
|
||||||
|
|
||||||
class T_Bofa
|
|
||||||
{
|
|
||||||
//TODO: Add some testcases that cover multiple lines and insertions
|
|
||||||
//Such as texts, objects and arrays
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
namespace Bofa.Testing.Parsing;
|
|
||||||
|
|
||||||
class T_BofaError
|
|
||||||
{
|
|
||||||
//TODO; add some testcases that fail the parser
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
namespace Bofa.Testing.Parsing;
|
|
||||||
using System;
|
|
||||||
using Bofa;
|
|
||||||
using Bofa.Builder;
|
|
||||||
class T_SingleLine
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
This class checks the validity of any single line bofa object
|
|
||||||
*/
|
|
||||||
|
|
||||||
[Test] //Any line that should be parsed as empty
|
|
||||||
public static void EmptyLine()
|
|
||||||
{
|
|
||||||
StringView[] lineArr = scope .(
|
|
||||||
"",
|
|
||||||
" ",
|
|
||||||
"\t",
|
|
||||||
" ",
|
|
||||||
"#asdasdasdasd",
|
|
||||||
" # asdasdasdasd",
|
|
||||||
"#"
|
|
||||||
);
|
|
||||||
|
|
||||||
BofaParser p = .();
|
|
||||||
for(let e in lineArr)
|
|
||||||
{
|
|
||||||
var r = p.[Friend]parseLine(e);
|
|
||||||
if(!r.IsEmpty)
|
|
||||||
Runtime.FatalError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test] //Some lines that should be parsed as text
|
|
||||||
public static void Text()
|
|
||||||
{
|
|
||||||
StringView[] lineArr = scope .(
|
|
||||||
"- text", //Depth 0
|
|
||||||
" - text", //Depth 1
|
|
||||||
" - TEasdasdas iodfjoidfiosduiofsd", //Depth 2
|
|
||||||
" - dadsadasdasdasfjrdfiofjiofdsghjniodfgdf" //Depth 3
|
|
||||||
);
|
|
||||||
BofaParser p = .();
|
|
||||||
for(int i < lineArr.Count)
|
|
||||||
{
|
|
||||||
var r = p.[Friend]parseLine(lineArr[i]);
|
|
||||||
if(!r.Ok || r.IsEmpty)
|
|
||||||
Runtime.FatalError();
|
|
||||||
|
|
||||||
if(r.Text.0 != i+1)
|
|
||||||
Runtime.FatalError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test] //Doing some parsing
|
|
||||||
public static void Parse()
|
|
||||||
{
|
|
||||||
StringView[] lineArr = scope .(
|
|
||||||
"n float 1223",
|
|
||||||
"n float 1.232",
|
|
||||||
"b bool true",
|
|
||||||
"b bool false",
|
|
||||||
"l line text goes here",
|
|
||||||
"bn BigNumber 3242343242354543",
|
|
||||||
"i integer 12423423",
|
|
||||||
"bi BigInteger 344234323454365",
|
|
||||||
"t text sdfsdgdfgdfgdf",
|
|
||||||
"t text ",
|
|
||||||
"c color redd 255 0 0",
|
|
||||||
"a array",
|
|
||||||
"o object"
|
|
||||||
);
|
|
||||||
BofaParser p = .();
|
|
||||||
for(var e in lineArr)
|
|
||||||
{
|
|
||||||
var r = p.[Friend]parseLine(e);
|
|
||||||
if(!r.Ok || r.IsEmpty || !r.IsBofa)
|
|
||||||
Runtime.FatalError();
|
|
||||||
delete r.Bofa.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
78
src/bofa.bf
78
src/bofa.bf
|
@ -1,78 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
using System;
|
|
||||||
class Bofa
|
|
||||||
{
|
|
||||||
public eBofaType Type;
|
|
||||||
public StringView TypeName;
|
|
||||||
public StringView Name;
|
|
||||||
public BofaValue Value;
|
|
||||||
|
|
||||||
private Bofa LastObject = null;
|
|
||||||
|
|
||||||
public ~this()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(Type == .Text)
|
|
||||||
delete Value.Text;
|
|
||||||
else if(Type == .Object && Value.Object != null)
|
|
||||||
DeleteDictionaryAndValues!(Value.Object);
|
|
||||||
else if(Type == .Array && Value.Array != null)
|
|
||||||
DeleteContainerAndItems!(Value.Array);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Insert(uint32 depth, Bofa toInsert, StringView toAdd = "")
|
|
||||||
{
|
|
||||||
if(depth > 0 && (LastObject == null || (LastObject.Type != .Array && LastObject.Type != .Object && LastObject.Type != .Text)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(depth > 0)
|
|
||||||
{
|
|
||||||
return LastObject.Insert(depth-1, toInsert, toAdd);
|
|
||||||
}
|
|
||||||
//Actually insert it now
|
|
||||||
switch(Type)
|
|
||||||
{
|
|
||||||
case .Text:
|
|
||||||
Value.Text.Append(scope $"\n{toAdd}");
|
|
||||||
case .Array:
|
|
||||||
Value.Array.Add(toInsert);
|
|
||||||
case .Object:
|
|
||||||
if(Value.Object.ContainsKey(toInsert.Name))
|
|
||||||
return false; //Error
|
|
||||||
Value.Object.Add(toInsert.Name, toInsert);
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LastObject = toInsert;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Finding specific entries easier
|
|
||||||
public Result<Bofa> this[StringView name]
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
if(Type != .Object)
|
|
||||||
return .Err;
|
|
||||||
if(!Value.Object.ContainsKey(name))
|
|
||||||
return .Err;
|
|
||||||
return .Ok(Value.Object[name]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<Bofa> this[uint32 number]
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
if(Type != .Array)
|
|
||||||
return .Err;
|
|
||||||
if(Value.Array.Count <= number)
|
|
||||||
return .Err;
|
|
||||||
return Value.Array[number];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static mixin GetValueOrDefault<T>(Result<T> result, T dfault)
|
|
||||||
{
|
|
||||||
result case .Err ? dfault : result
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,287 +0,0 @@
|
||||||
namespace Bofa;
|
|
||||||
using System;
|
|
||||||
struct BofaParser
|
|
||||||
{
|
|
||||||
public BofaResult Parse(StringView pLine)
|
|
||||||
{
|
|
||||||
BofaResult toReturn = new .();
|
|
||||||
toReturn.[Friend]_data = new String(pLine);
|
|
||||||
var enumerator = toReturn.[Friend]_data.Split('\n');
|
|
||||||
for(let e in enumerator)
|
|
||||||
{ //Loop through each line
|
|
||||||
var res = parseLine(e); //Handle the result and do the inserting
|
|
||||||
if(res.IsEmpty)
|
|
||||||
continue;
|
|
||||||
if(!res.Ok)
|
|
||||||
{
|
|
||||||
toReturn.[Friend]OK = false;
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
var result = toReturn.[Friend]Insert(res);
|
|
||||||
if(result == false)
|
|
||||||
{
|
|
||||||
toReturn.[Friend]OK = false;
|
|
||||||
if(res.IsBofa)
|
|
||||||
delete res.Bofa.1;
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///Atttempts to parse a single line into a bofa object and returns its depth
|
|
||||||
private lineParserResult parseLine(StringView pLine)
|
|
||||||
{
|
|
||||||
StringView line = pLine; //So that we can work on it
|
|
||||||
|
|
||||||
#region Depth
|
|
||||||
//Get the depth of the line
|
|
||||||
uint32 depth = 0;
|
|
||||||
var hasContent = false; //In order to check wether it just ran out, or wether we actually have content
|
|
||||||
for(var c in line)
|
|
||||||
{
|
|
||||||
if(c == ' ' || c == ' ')
|
|
||||||
{
|
|
||||||
depth++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(c == '#')
|
|
||||||
return .(); //Comment
|
|
||||||
hasContent = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!hasContent)
|
|
||||||
return .(); //Is empty
|
|
||||||
line = .(line, depth);
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Type
|
|
||||||
//Get the type of the line
|
|
||||||
let type = NextPart(line);
|
|
||||||
line = type.1;
|
|
||||||
if(type.0 == "") //Shouldnt be empty
|
|
||||||
return .();
|
|
||||||
else if(type.0 == "-")
|
|
||||||
return .(type.1, depth+1);
|
|
||||||
//We have now assured, that the object we are handling is seemingly a normal one
|
|
||||||
StringView typeName;
|
|
||||||
switch(type.0)
|
|
||||||
{
|
|
||||||
case "c":
|
|
||||||
let tnameres = NextPart(line);
|
|
||||||
if(tnameres.0 == "")
|
|
||||||
return .(false);
|
|
||||||
line = tnameres.1;
|
|
||||||
typeName = tnameres.0;
|
|
||||||
case "n":
|
|
||||||
typeName = "Number";
|
|
||||||
case "b":
|
|
||||||
typeName = "Boolean";
|
|
||||||
case "l":
|
|
||||||
typeName = "Line";
|
|
||||||
case "bn":
|
|
||||||
typeName = "BigNumber";
|
|
||||||
case "i":
|
|
||||||
typeName = "Integer";
|
|
||||||
case "bi":
|
|
||||||
typeName = "BigInteger";
|
|
||||||
case "t":
|
|
||||||
typeName = "Text";
|
|
||||||
case "a":
|
|
||||||
typeName = "Array";
|
|
||||||
case "o":
|
|
||||||
typeName = "Object";
|
|
||||||
default:
|
|
||||||
return .(false); //Unsupported type error
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Name
|
|
||||||
//Get the name and return if its a array or object
|
|
||||||
let nameres = NextPart(line);
|
|
||||||
line = nameres.1;
|
|
||||||
if(nameres.0 == "")
|
|
||||||
return .(false);
|
|
||||||
|
|
||||||
if(type.0 == "o" || type.0 == "a")
|
|
||||||
{
|
|
||||||
Bofa toReturn = new Bofa();
|
|
||||||
toReturn.Name = nameres.0;
|
|
||||||
toReturn.TypeName = typeName;
|
|
||||||
if(type.0 == "o")
|
|
||||||
{
|
|
||||||
toReturn.Type = .Object;
|
|
||||||
toReturn.Value.Object = new .();
|
|
||||||
return .(toReturn, depth);
|
|
||||||
}
|
|
||||||
toReturn.Type = .Array;
|
|
||||||
toReturn.Value.Array = new .();
|
|
||||||
return .(toReturn, depth);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Value
|
|
||||||
if(line == "")
|
|
||||||
return .(false);
|
|
||||||
Bofa toReturn = new .();
|
|
||||||
toReturn.Name = nameres.0;
|
|
||||||
toReturn.TypeName = typeName;
|
|
||||||
switch(type.0)
|
|
||||||
{
|
|
||||||
case "n":
|
|
||||||
toReturn.Type = .Number;
|
|
||||||
var result = float.Parse(line);
|
|
||||||
if(result case .Err)
|
|
||||||
{
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
toReturn.Value.Number = result.Value;
|
|
||||||
case "b":
|
|
||||||
if(line == "true")
|
|
||||||
toReturn.Value.Boolean = true;
|
|
||||||
else if(line == "false")
|
|
||||||
toReturn.Value.Boolean = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
toReturn.Type = .Boolean;
|
|
||||||
case "l":
|
|
||||||
toReturn.Value.Line = line;
|
|
||||||
toReturn.Type = .Line;
|
|
||||||
case "bn":
|
|
||||||
toReturn.Type = .BigNumber;
|
|
||||||
var result = double.Parse(line);
|
|
||||||
if(result case .Err)
|
|
||||||
{
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
toReturn.Value.BigNumber = result.Value;
|
|
||||||
case "i":
|
|
||||||
toReturn.Type = .Integer;
|
|
||||||
var result = int32.Parse(line);
|
|
||||||
if(result case .Err)
|
|
||||||
{
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
toReturn.Value.Integer = result.Value;
|
|
||||||
case "bi":
|
|
||||||
toReturn.Type = .BigInteger;
|
|
||||||
var result = int64.Parse(line);
|
|
||||||
if(result case .Err)
|
|
||||||
{
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
toReturn.Value.BigInteger = result.Value;
|
|
||||||
case "t":
|
|
||||||
toReturn.Value.Text = new .(line);
|
|
||||||
toReturn.Type = .Text;
|
|
||||||
case "c":
|
|
||||||
toReturn.Value.Custom = line;
|
|
||||||
toReturn.Type = .Custom;
|
|
||||||
default:
|
|
||||||
delete toReturn;
|
|
||||||
return .(false);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
//If this ever returns something went wrong
|
|
||||||
return .(toReturn,depth);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static (StringView, StringView) NextPart(StringView pLine)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
for(var c in pLine)
|
|
||||||
{
|
|
||||||
if(c == ' ')
|
|
||||||
{
|
|
||||||
if(@c.GetNext() case .Ok(let val))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return (.(pLine, 0, (i < pLine.Length) ? i-1 : i), .(pLine, i));
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct lineParserResult
|
|
||||||
{ //I hate that this is necessary to handle parseLine, but its just so much data that needs to be moved
|
|
||||||
private bool ok = true;
|
|
||||||
private bool isEmpty = false;
|
|
||||||
private uint32 depth = 0;
|
|
||||||
|
|
||||||
private bool isBofa = true; //Wether this is a bofa or a string extension
|
|
||||||
private StringView text = "";
|
|
||||||
private Bofa bofa = null;
|
|
||||||
|
|
||||||
public this(bool pIsEmpty = true)
|
|
||||||
{ //Either for errors or incase its an empty line
|
|
||||||
//the difference is that empty lines should be skipped, while an error would
|
|
||||||
if(pIsEmpty)
|
|
||||||
isEmpty = true;
|
|
||||||
else
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(StringView pText, uint32 pDepth = 0)
|
|
||||||
{ //For text addendums
|
|
||||||
depth = pDepth;
|
|
||||||
isBofa = false;
|
|
||||||
text = pText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(Bofa pBofa, uint32 pDepth = 0)
|
|
||||||
{ //For normal bofa objects
|
|
||||||
depth = pDepth;
|
|
||||||
bofa = pBofa;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Ok
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEmpty
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
return isEmpty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsBofa
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
return isBofa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public (uint32, Bofa) Bofa
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
return (depth, bofa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public (uint32, StringView) Text
|
|
||||||
{
|
|
||||||
public get {
|
|
||||||
return (depth, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +1,15 @@
|
||||||
namespace Bofa;
|
namespace Bofa;
|
||||||
|
|
||||||
enum eBofaType
|
enum EBofaType
|
||||||
{
|
{
|
||||||
Number,
|
Line, //String without \n
|
||||||
Boolean,
|
Text, //String with \n
|
||||||
Line,
|
Number, //32bit floating point number
|
||||||
BigNumber,
|
BigNumber, //64bit floating point number
|
||||||
Integer,
|
Integer, //32bit signed integer
|
||||||
BigInteger,
|
BigInteger, //64bit signed integer
|
||||||
Text,
|
Boolean, //8bit true or false
|
||||||
Custom,
|
Object, // Key-Value container
|
||||||
Array,
|
Array, //Numeric container
|
||||||
Object
|
Custom //String with a type attached to it
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue