From ae2ff31f21ba4306bf11bae62b9af5cd124240ea Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 15:31:19 +0200 Subject: [PATCH 01/22] started another rewrite --- src/BofaAbleAttribute.bf | 13 +++++++++++ src/BofaAttribute.bf | 29 +++++++++++++++++++++++++ src/BofaReflector.bf | 47 ++++++++++++++++++++++++++++++++++++++++ src/IBofaParseable.bf | 7 ++++++ 4 files changed, 96 insertions(+) create mode 100644 src/BofaAbleAttribute.bf create mode 100644 src/BofaAttribute.bf create mode 100644 src/BofaReflector.bf create mode 100644 src/IBofaParseable.bf diff --git a/src/BofaAbleAttribute.bf b/src/BofaAbleAttribute.bf new file mode 100644 index 0000000..0e7170a --- /dev/null +++ b/src/BofaAbleAttribute.bf @@ -0,0 +1,13 @@ +namespace Bofa; + +using System; + +struct BofaAbleAttribute : Attribute +{ + public StringView Name; + + public this(StringView pName) + { + Name = pName; + } +} \ No newline at end of file diff --git a/src/BofaAttribute.bf b/src/BofaAttribute.bf new file mode 100644 index 0000000..8da58ec --- /dev/null +++ b/src/BofaAttribute.bf @@ -0,0 +1,29 @@ +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, "}"); + } +} \ No newline at end of file diff --git a/src/BofaReflector.bf b/src/BofaReflector.bf new file mode 100644 index 0000000..09bb373 --- /dev/null +++ b/src/BofaReflector.bf @@ -0,0 +1,47 @@ +namespace Bofa; + +using System; +using System.Reflection; + +class BofaReflector +{ + + ///Parse an object into its bofa representation + public static void ToBofa(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() 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(value, fieldContent); + buffer.Value.Object.Add(fieldContent.Name, fieldContent); + } + } + } + + } +} \ No newline at end of file diff --git a/src/IBofaParseable.bf b/src/IBofaParseable.bf new file mode 100644 index 0000000..1285338 --- /dev/null +++ b/src/IBofaParseable.bf @@ -0,0 +1,7 @@ +namespace Bofa; + +interface IBofaParseable +{ + public void ToBofa(Bofa target); + public void FromBofa(Bofa input); +} \ No newline at end of file From 90e19222e7ccb4d9da530e062d2674e305255bec Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 15:31:19 +0200 Subject: [PATCH 02/22] Added EBofaType enum --- src/BofaAbleAttribute.bf | 13 -- src/BofaAttribute.bf | 29 --- src/BofaBuilder.bf | 233 ---------------------- src/BofaReflector.bf | 47 ----- src/BofaResult.bf | 88 --------- src/BofaValue.bf | 17 -- src/IBofaParseable.bf | 7 - src/Testing/Parsing/T_Bofa.bf | 7 - src/Testing/Parsing/T_BofaError.bf | 6 - src/Testing/Parsing/T_SingleLine.bf | 81 -------- src/bofa.bf | 78 -------- src/bofaParser.bf | 287 ---------------------------- src/eBofaType.bf | 22 +-- 13 files changed, 11 insertions(+), 904 deletions(-) delete mode 100644 src/BofaAbleAttribute.bf delete mode 100644 src/BofaAttribute.bf delete mode 100644 src/BofaBuilder.bf delete mode 100644 src/BofaReflector.bf delete mode 100644 src/BofaResult.bf delete mode 100644 src/BofaValue.bf delete mode 100644 src/IBofaParseable.bf delete mode 100644 src/Testing/Parsing/T_Bofa.bf delete mode 100644 src/Testing/Parsing/T_BofaError.bf delete mode 100644 src/Testing/Parsing/T_SingleLine.bf delete mode 100644 src/bofa.bf delete mode 100644 src/bofaParser.bf diff --git a/src/BofaAbleAttribute.bf b/src/BofaAbleAttribute.bf deleted file mode 100644 index 0e7170a..0000000 --- a/src/BofaAbleAttribute.bf +++ /dev/null @@ -1,13 +0,0 @@ -namespace Bofa; - -using System; - -struct BofaAbleAttribute : Attribute -{ - public StringView Name; - - public this(StringView pName) - { - Name = pName; - } -} \ No newline at end of file diff --git a/src/BofaAttribute.bf b/src/BofaAttribute.bf deleted file mode 100644 index 8da58ec..0000000 --- a/src/BofaAttribute.bf +++ /dev/null @@ -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, "}"); - } -} \ No newline at end of file diff --git a/src/BofaBuilder.bf b/src/BofaBuilder.bf deleted file mode 100644 index 841954e..0000000 --- a/src/BofaBuilder.bf +++ /dev/null @@ -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 Members; - - public this(String name, String type, String typeName, String value, Span 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 values; - private List valueList = new .(); - public this(params Span 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 input) - { - return .(new .(name), "o", null,null,input); - } - - public static b Array(StringView name, params Span 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 input) - { - return .("-", "o", null, null, input); - } - public static b ArrayA(params Span 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 .())); - } -} \ No newline at end of file diff --git a/src/BofaReflector.bf b/src/BofaReflector.bf deleted file mode 100644 index 09bb373..0000000 --- a/src/BofaReflector.bf +++ /dev/null @@ -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 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() 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(value, fieldContent); - buffer.Value.Object.Add(fieldContent.Name, fieldContent); - } - } - } - - } -} \ No newline at end of file diff --git a/src/BofaResult.bf b/src/BofaResult.bf deleted file mode 100644 index ca5a8e2..0000000 --- a/src/BofaResult.bf +++ /dev/null @@ -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 _contents = new Dictionary(10); //Storage - private List _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 this[StringView pValue] - { - public get { - if(!_contents.ContainsKey(pValue)) - return .Err; - return _contents[pValue]; - } - } - - public Result GetByName(StringView pValue) - { - return this[pValue]; - } - -} \ No newline at end of file diff --git a/src/BofaValue.bf b/src/BofaValue.bf deleted file mode 100644 index ae1e8f8..0000000 --- a/src/BofaValue.bf +++ /dev/null @@ -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 Object = null; - public List Array = null; -} \ No newline at end of file diff --git a/src/IBofaParseable.bf b/src/IBofaParseable.bf deleted file mode 100644 index 1285338..0000000 --- a/src/IBofaParseable.bf +++ /dev/null @@ -1,7 +0,0 @@ -namespace Bofa; - -interface IBofaParseable -{ - public void ToBofa(Bofa target); - public void FromBofa(Bofa input); -} \ No newline at end of file diff --git a/src/Testing/Parsing/T_Bofa.bf b/src/Testing/Parsing/T_Bofa.bf deleted file mode 100644 index fef00e0..0000000 --- a/src/Testing/Parsing/T_Bofa.bf +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/src/Testing/Parsing/T_BofaError.bf b/src/Testing/Parsing/T_BofaError.bf deleted file mode 100644 index 597759b..0000000 --- a/src/Testing/Parsing/T_BofaError.bf +++ /dev/null @@ -1,6 +0,0 @@ -namespace Bofa.Testing.Parsing; - -class T_BofaError -{ - //TODO; add some testcases that fail the parser -} \ No newline at end of file diff --git a/src/Testing/Parsing/T_SingleLine.bf b/src/Testing/Parsing/T_SingleLine.bf deleted file mode 100644 index 2db3731..0000000 --- a/src/Testing/Parsing/T_SingleLine.bf +++ /dev/null @@ -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; - } - } -} \ No newline at end of file diff --git a/src/bofa.bf b/src/bofa.bf deleted file mode 100644 index 62a7191..0000000 --- a/src/bofa.bf +++ /dev/null @@ -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 this[StringView name] - { - public get { - if(Type != .Object) - return .Err; - if(!Value.Object.ContainsKey(name)) - return .Err; - return .Ok(Value.Object[name]); - } - } - - public Result 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(Result result, T dfault) - { - result case .Err ? dfault : result - } -} \ No newline at end of file diff --git a/src/bofaParser.bf b/src/bofaParser.bf deleted file mode 100644 index fa932c8..0000000 --- a/src/bofaParser.bf +++ /dev/null @@ -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); - } - } - - } - -} \ No newline at end of file diff --git a/src/eBofaType.bf b/src/eBofaType.bf index 7bc06e9..d3e253c 100644 --- a/src/eBofaType.bf +++ b/src/eBofaType.bf @@ -1,15 +1,15 @@ namespace Bofa; -enum eBofaType +enum EBofaType { - Number, - Boolean, - Line, - BigNumber, - Integer, - BigInteger, - Text, - Custom, - Array, - Object + Line, //String without \n + Text, //String with \n + Number, //32bit floating point number + BigNumber, //64bit floating point number + Integer, //32bit signed integer + BigInteger, //64bit signed integer + Boolean, //8bit true or false + Object, // Key-Value container + Array, //Numeric container + Custom //String with a type attached to it } \ No newline at end of file From cf0e2ddb9388a901fd3307afad82fd947a15487a Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 15:31:19 +0200 Subject: [PATCH 03/22] Added BofaValue union struct --- src/BofaValue.bf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/BofaValue.bf diff --git a/src/BofaValue.bf b/src/BofaValue.bf new file mode 100644 index 0000000..fea68af --- /dev/null +++ b/src/BofaValue.bf @@ -0,0 +1,19 @@ +namespace Bofa; + +using System; +using System.Collections; + +[Union] +struct BofaValue +{ + StringView Line; + StringView Text; + float Number; + double BigNumber; + int32 Integer; + int64 BigInteger; + bool Boolean; + String Custom; + Bofa Object; + Bofa Array; +} \ No newline at end of file From 0de995d9b6bfd2018ede156103b18885c86ee2af Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 15:31:20 +0200 Subject: [PATCH 04/22] Added Bofa class --- src/Bofa.bf | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/Bofa.bf diff --git a/src/Bofa.bf b/src/Bofa.bf new file mode 100644 index 0000000..648b44e --- /dev/null +++ b/src/Bofa.bf @@ -0,0 +1,11 @@ +namespace Bofa; + +using System; + +class Bofa +{ + public StringView Name; + public EBofaType Type; + public StringView Typename; + public BofaValue Value; +} \ No newline at end of file From 3907da566dd231187755c81d7c64f5089d4449ad Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 15:31:20 +0200 Subject: [PATCH 05/22] Created Default test --- src/Testing/Default.bf | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/Testing/Default.bf diff --git a/src/Testing/Default.bf b/src/Testing/Default.bf new file mode 100644 index 0000000..b09dd4f --- /dev/null +++ b/src/Testing/Default.bf @@ -0,0 +1,5 @@ +namespace Bofa.Testing; + +class Default +{ +} \ No newline at end of file From 0231bdc13aef9f561a4edb5e3b5772a07256dc99 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 16:24:09 +0200 Subject: [PATCH 06/22] Added ParserEntry class and created BofaParser class --- src/BofaParser.bf | 5 +++++ src/Parser/ParserEntry.bf | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/BofaParser.bf create mode 100644 src/Parser/ParserEntry.bf diff --git a/src/BofaParser.bf b/src/BofaParser.bf new file mode 100644 index 0000000..607f183 --- /dev/null +++ b/src/BofaParser.bf @@ -0,0 +1,5 @@ +namespace Bofa; + +class BofaParser +{ +} \ No newline at end of file diff --git a/src/Parser/ParserEntry.bf b/src/Parser/ParserEntry.bf new file mode 100644 index 0000000..c66c151 --- /dev/null +++ b/src/Parser/ParserEntry.bf @@ -0,0 +1,16 @@ +namespace Bofa.Parser; + +using System; + +struct ParserEntry +{ + public bool IsBofaOrText = true; //True == Bofa, False == Text + public EntryUnion Data; + + [Union] + public struct EntryUnion + { + public Bofa Bofa; + public StringView Text; + } +} \ No newline at end of file From c2940ad404ccc76b3b83242d9e28cee77a6ad9cb Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 16:28:02 +0200 Subject: [PATCH 07/22] Seperated out ParserEntryUnion --- src/Parser/ParserEntry.bf | 9 +-------- src/Parser/ParserEntryUnion.bf | 10 ++++++++++ 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 src/Parser/ParserEntryUnion.bf diff --git a/src/Parser/ParserEntry.bf b/src/Parser/ParserEntry.bf index c66c151..9899a6f 100644 --- a/src/Parser/ParserEntry.bf +++ b/src/Parser/ParserEntry.bf @@ -5,12 +5,5 @@ using System; struct ParserEntry { public bool IsBofaOrText = true; //True == Bofa, False == Text - public EntryUnion Data; - - [Union] - public struct EntryUnion - { - public Bofa Bofa; - public StringView Text; - } + public ParserEntryUnion Data; } \ No newline at end of file diff --git a/src/Parser/ParserEntryUnion.bf b/src/Parser/ParserEntryUnion.bf new file mode 100644 index 0000000..531f037 --- /dev/null +++ b/src/Parser/ParserEntryUnion.bf @@ -0,0 +1,10 @@ +namespace Bofa.Parser; + +using System; + +[Union] +struct ParserEntryUnion +{ + public Bofa Bofa; + public StringView Text; +} \ No newline at end of file From 9f1f8a408818621bd82f75fd1ed6abed28b75887 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 16:33:12 +0200 Subject: [PATCH 08/22] Added EParserEntryType --- src/Parser/EParserEntryType.bf | 8 ++++++++ src/Parser/ParserEntry.bf | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/Parser/EParserEntryType.bf diff --git a/src/Parser/EParserEntryType.bf b/src/Parser/EParserEntryType.bf new file mode 100644 index 0000000..f3acf82 --- /dev/null +++ b/src/Parser/EParserEntryType.bf @@ -0,0 +1,8 @@ +namespace Bofa.Parser; + +enum EParserEntryType +{ + Bofa, + Text, + Empty +} \ No newline at end of file diff --git a/src/Parser/ParserEntry.bf b/src/Parser/ParserEntry.bf index 9899a6f..b7a21bd 100644 --- a/src/Parser/ParserEntry.bf +++ b/src/Parser/ParserEntry.bf @@ -4,6 +4,6 @@ using System; struct ParserEntry { - public bool IsBofaOrText = true; //True == Bofa, False == Text + public EParserEntryType Type; public ParserEntryUnion Data; } \ No newline at end of file From f814674132c9e9239af10f9530d9cc62d844bfdb Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 3 Aug 2024 17:04:46 +0200 Subject: [PATCH 09/22] Finished ParserEntry class --- src/Parser/ParserEntry.bf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Parser/ParserEntry.bf b/src/Parser/ParserEntry.bf index b7a21bd..d720a68 100644 --- a/src/Parser/ParserEntry.bf +++ b/src/Parser/ParserEntry.bf @@ -4,6 +4,7 @@ using System; struct ParserEntry { + public uint64 Line; public EParserEntryType Type; public ParserEntryUnion Data; } \ No newline at end of file From 6d2eab4e44dd6eb600d86b79c52b5cfeeb0399ee Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 5 Aug 2024 00:46:48 +0200 Subject: [PATCH 10/22] Basic implementation of parser --- BeefSpace.toml | 3 +++ src/BofaParser.bf | 43 +++++++++++++++++++++++++++++++++++++++ src/Parser/ParserEntry.bf | 3 ++- src/Testing/Default.bf | 9 ++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/BeefSpace.toml b/BeefSpace.toml index 0bb5a2b..ba54fc1 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -3,3 +3,6 @@ Projects = {Bofa = {Path = "."}} [Workspace] StartupProject = "Bofa" + +[Configs.Test.Win64] +LargeStrings = true diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 607f183..909572c 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -1,5 +1,48 @@ namespace Bofa; +using System; +using System.IO; +using System.Collections; + +using Bofa.Parser; + class BofaParser { + + public static Result Parse(StringView pToParse, List pResult) + { + StringStream stream = new .(pToParse, .Reference); + defer delete stream; + return Parse(stream, pResult); + } + + public static Result Parse(Stream pToParse, List pResult) + { + if(pToParse == null || pResult == null) + return .Err(-1); + + StreamReader reader = new .(pToParse); + defer delete reader; + + int64 line = 1; + while(reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you + { + String l = scope .(); + if(reader.ReadLine(l) case .Err) + return .Err(-2); + var entry = ParseLine(l, line); + line++; + } + + return .Ok; + } + + private static ParserEntry ParseLine(StringView pLine, int64 pLineNumber) + { + StringView line = pLine; + ParserEntry toReturn = .(); + + uint32 depth; + return .(); + } } \ No newline at end of file diff --git a/src/Parser/ParserEntry.bf b/src/Parser/ParserEntry.bf index d720a68..d1b1ecf 100644 --- a/src/Parser/ParserEntry.bf +++ b/src/Parser/ParserEntry.bf @@ -4,7 +4,8 @@ using System; struct ParserEntry { - public uint64 Line; + public int64 Line; + public int64 Depth = 0; public EParserEntryType Type; public ParserEntryUnion Data; } \ No newline at end of file diff --git a/src/Testing/Default.bf b/src/Testing/Default.bf index b09dd4f..b8e89bf 100644 --- a/src/Testing/Default.bf +++ b/src/Testing/Default.bf @@ -1,5 +1,14 @@ namespace Bofa.Testing; +using System; +using System.IO; + class Default { + [Test] + public static void Default_Test_1() + { + BofaParser.Parse("Without an ending", scope .()).IgnoreError(); + + } } \ No newline at end of file From 7da72c9344f1ca1792469845c5cf987fbfe4a0bf Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sun, 11 Aug 2024 15:33:18 +0200 Subject: [PATCH 11/22] Added back old parsing algorithm --- src/Bofa.bf | 15 ++ src/BofaParser.bf | 272 +++++++++++++++++++++++++++++++-- src/BofaValue.bf | 20 +-- src/Parser/BofaParserInsert.bf | 42 +++++ src/Parser/EParserEntryType.bf | 3 +- src/Testing/Default.bf | 21 ++- 6 files changed, 345 insertions(+), 28 deletions(-) create mode 100644 src/Parser/BofaParserInsert.bf diff --git a/src/Bofa.bf b/src/Bofa.bf index 648b44e..8544b43 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -4,8 +4,23 @@ using System; class Bofa { + private String _line = null; //The actual line + private Bofa _lastObject = null; //If we are a container we keep track of the last container inside of us + public StringView Name; public EBofaType Type; public StringView Typename; public BofaValue Value; + + public ~this() + { + if(_line != null) + delete _line; + if(Type == .Text) + delete Value.Text; + else if(Type == .Object) + DeleteDictionaryAndValues!(Value.Object); + else if(Type == .Array) + DeleteContainerAndItems!(Value.Array); + } } \ No newline at end of file diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 909572c..88e1c48 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -8,41 +8,283 @@ using Bofa.Parser; class BofaParser { - - public static Result Parse(StringView pToParse, List pResult) + public static void Parse(StringView pToParse, List pResult, List pErrors) { StringStream stream = new .(pToParse, .Reference); defer delete stream; - return Parse(stream, pResult); + Parse(stream, pResult, pErrors); } - public static Result Parse(Stream pToParse, List pResult) + public static void Parse(Stream pToParse, List pResult, List pErrors) { - if(pToParse == null || pResult == null) - return .Err(-1); + if (pToParse == null || pResult == null) + { //Cannot parse what doesnt exist + pErrors.Add(-1); + return; + } StreamReader reader = new .(pToParse); defer delete reader; int64 line = 1; - while(reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you + while (reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you { - String l = scope .(); - if(reader.ReadLine(l) case .Err) - return .Err(-2); + String l = new .(); + if (reader.ReadLine(l) case .Err) + { //Despite data being here, we cannot read it + pErrors.Add(-2); + return; + } + var entry = ParseLine(l, line); + if(!(entry.Type == .Bofa || entry.Type == .Text)) + delete l; //In these cases we have no useable data + if(entry.Type == .Error) + pErrors.Add(line); + + //If we are on the lowest level we can just add them here + if(entry.Depth == 0 && entry.Type ==.Bofa) + { + if(pResult.FindIndex(scope (x) => { return x.Name == entry.Data.Bofa.Name;}) < 0) + pResult.Add(entry.Data.Bofa); + else + pErrors.Add(entry.Line); //Dublicate name error + } + else if(entry.Depth == 1 && entry.Type == .Text) + { + if(pResult[pResult.Count-1].Type == .Text) + pResult[pResult.Count-1].Value.Text.Append(entry.Data.Text); + else + pErrors.Add(entry.Line); //Bad text error + } + + //if(pResult[pResult.Count-1].[Friend]_Insert(&entry) case .Err) + //pErrors.Add(line); line++; } - return .Ok; + return; //Being done normally } - private static ParserEntry ParseLine(StringView pLine, int64 pLineNumber) + private static ParserEntry ParseLine(String pLine, int64 pLineNumber) { StringView line = pLine; ParserEntry toReturn = .(); - - uint32 depth; - return .(); + toReturn.Line = pLineNumber; + +#region Depth + 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 == '#') + { + toReturn.Type = .Empty; + return toReturn; //Comment + } + hasContent = true; + break; + } + if (!hasContent) + { + toReturn.Type = .Empty; + return toReturn; //Is empty + } + line = .(line, depth); + toReturn.Depth = depth; +#endregion + +#region Type + //Get the type of the line + let type = NextPart(line); + line = type.1; + if (type.0 == "") //This should never be reached + { + Runtime.FatalError("Unreachable code reached"); + toReturn.Type = .Error; + return toReturn; + } + else if (type.0 == "-") + { + toReturn.Type = .Text; + toReturn.Data.Text = line; + toReturn.Depth = depth + 1; + return toReturn; + + } + //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 == "") + { //Its of type custom but ends after the custom + toReturn.Type = .Error; + return toReturn; + } + 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: + toReturn.Type = .Error; + return toReturn; //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 == "") + { + toReturn.Type = .Error; + return toReturn; + } + + if (type.0 == "o" || type.0 == "a") + { + Bofa bofaRes = new Bofa(); + bofaRes.Name = nameres.0; + bofaRes.Typename = typeName; + if (type.0 == "o") + { + bofaRes.Type = .Object; + bofaRes.Value.Object = new .(); + toReturn.Type = .Bofa; + toReturn.Data.Bofa = bofaRes; + return toReturn; + } + bofaRes.Type = .Array; + bofaRes.Value.Array = new .(); + toReturn.Type = .Bofa; + toReturn.Data.Bofa = bofaRes; + return toReturn; + } +#endregion + +#region Value + if (line == "") + { + toReturn.Type = .Error; + return toReturn; + } + Bofa bofaRes = new .(); + bofaRes.Name = nameres.0; + bofaRes.Typename = typeName; + switch (type.0) + { + case "n": + bofaRes.Type = .Number; + var result = float.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.Number = result.Value; + case "b": + if (line == "true") + bofaRes.Value.Boolean = true; + else if (line == "false") + bofaRes.Value.Boolean = false; + else + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Type = .Boolean; + case "l": + bofaRes.Value.Line = line; + bofaRes.Type = .Line; + case "bn": + bofaRes.Type = .BigNumber; + var result = double.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.BigNumber = result.Value; + case "i": + bofaRes.Type = .Integer; + var result = int32.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.Integer = result.Value; + case "bi": + bofaRes.Type = .BigInteger; + var result = int64.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.BigInteger = result.Value; + case "t": + bofaRes.Value.Text = new String(line); + bofaRes.Type = .Text; + case "c": + bofaRes.Value.Custom = line; + bofaRes.Type = .Custom; + default: //Unknown type + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } +#endregion + //If this ever returns something went wrong + bofaRes.[Friend]_line = pLine; + toReturn.Type = .Bofa; + toReturn.Data.Bofa = bofaRes; + return toReturn; + } + + 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)); } } \ No newline at end of file diff --git a/src/BofaValue.bf b/src/BofaValue.bf index fea68af..ad60bd0 100644 --- a/src/BofaValue.bf +++ b/src/BofaValue.bf @@ -6,14 +6,14 @@ using System.Collections; [Union] struct BofaValue { - StringView Line; - StringView Text; - float Number; - double BigNumber; - int32 Integer; - int64 BigInteger; - bool Boolean; - String Custom; - Bofa Object; - Bofa Array; + public StringView Line; + public String Text; + public float Number; + public double BigNumber; + public int32 Integer; + public int64 BigInteger; + public bool Boolean; + public StringView Custom; + public Dictionary Object; + public List Array; } \ No newline at end of file diff --git a/src/Parser/BofaParserInsert.bf b/src/Parser/BofaParserInsert.bf new file mode 100644 index 0000000..4615272 --- /dev/null +++ b/src/Parser/BofaParserInsert.bf @@ -0,0 +1,42 @@ +namespace Bofa; + +using Bofa.Parser; + +using System; + +extension Bofa +{ + private Result _Insert(ParserEntry* pToAdd) + { + //See if we can insert and do so + if(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1)) + { + if(pToAdd.Type == .Text && _lastObject.Type == .Text) + { + _lastObject.Value.Text.Append(pToAdd.Data.Text); + return .Ok; + } + else if(_lastObject.Type == .Object) + { + _lastObject.Value.Object.Add(pToAdd.Data.Bofa.Name, pToAdd.Data.Bofa); + _lastObject._lastObject = pToAdd.Data.Bofa; + return .Ok; + + } + else if(_lastObject.Type == .Array) + { + _lastObject.Value.Array.Add(pToAdd.Data.Bofa); + _lastObject._lastObject = pToAdd.Data.Bofa; + return .Ok; + } + return .Err; //Cannot insert here + } + + //Can we even go deeper + if(!(_lastObject.Type == .Object || _lastObject.Type == .Array)) + return .Err; + + pToAdd.Depth--; + return _lastObject._Insert(pToAdd); + } +} \ No newline at end of file diff --git a/src/Parser/EParserEntryType.bf b/src/Parser/EParserEntryType.bf index f3acf82..1d89ff5 100644 --- a/src/Parser/EParserEntryType.bf +++ b/src/Parser/EParserEntryType.bf @@ -4,5 +4,6 @@ enum EParserEntryType { Bofa, Text, - Empty + Empty, + Error } \ No newline at end of file diff --git a/src/Testing/Default.bf b/src/Testing/Default.bf index b8e89bf..0510b75 100644 --- a/src/Testing/Default.bf +++ b/src/Testing/Default.bf @@ -2,13 +2,30 @@ namespace Bofa.Testing; using System; using System.IO; +using System.Collections; class Default { [Test] public static void Default_Test_1() { - BofaParser.Parse("Without an ending", scope .()).IgnoreError(); - + String content = """ + t text goes here + - Text addendum + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + + + + + + + + + + DeleteContainerAndItems!(output); + delete errors; } } \ No newline at end of file From bd07c4b1511b55b9fc2333fd4168190af4e6bb3a Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Wed, 14 Aug 2024 16:56:25 +0200 Subject: [PATCH 12/22] finished basic parsing --- src/BofaParser.bf | 24 ++++++- src/Parser/BofaParserInsert.bf | 39 ++++++------ src/Testing/Default.bf | 111 ++++++++++++++++++++++++++++++++- src/Testing/Profiling.bf | 5 ++ 4 files changed, 156 insertions(+), 23 deletions(-) create mode 100644 src/Testing/Profiling.bf diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 88e1c48..85b36d8 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -39,8 +39,15 @@ class BofaParser var entry = ParseLine(l, line); if(!(entry.Type == .Bofa || entry.Type == .Text)) delete l; //In these cases we have no useable data + if(entry.Type == .Empty) + { + line++; + continue; + } if(entry.Type == .Error) pErrors.Add(line); + if(entry.Type == .Text) + defer delete l; //If we are on the lowest level we can just add them here if(entry.Depth == 0 && entry.Type ==.Bofa) @@ -48,18 +55,28 @@ class BofaParser if(pResult.FindIndex(scope (x) => { return x.Name == entry.Data.Bofa.Name;}) < 0) pResult.Add(entry.Data.Bofa); else + { pErrors.Add(entry.Line); //Dublicate name error + delete entry.Data.Bofa; + } } else if(entry.Depth == 1 && entry.Type == .Text) { if(pResult[pResult.Count-1].Type == .Text) - pResult[pResult.Count-1].Value.Text.Append(entry.Data.Text); + pResult[pResult.Count-1].Value.Text.Append(scope $"\n{entry.Data.Text}"); else pErrors.Add(entry.Line); //Bad text error } + else + { + entry.Depth--; + if(pResult[pResult.Count-1].[Friend]_Insert(&entry) case .Err) + { + pErrors.Add(line); + delete entry.Data.Bofa; + } + } - //if(pResult[pResult.Count-1].[Friend]_Insert(&entry) case .Err) - //pErrors.Add(line); line++; } @@ -167,6 +184,7 @@ class BofaParser if (type.0 == "o" || type.0 == "a") { Bofa bofaRes = new Bofa(); + bofaRes.[Friend]_line = pLine; bofaRes.Name = nameres.0; bofaRes.Typename = typeName; if (type.0 == "o") diff --git a/src/Parser/BofaParserInsert.bf b/src/Parser/BofaParserInsert.bf index 4615272..bbb6dc3 100644 --- a/src/Parser/BofaParserInsert.bf +++ b/src/Parser/BofaParserInsert.bf @@ -11,29 +11,32 @@ extension Bofa //See if we can insert and do so if(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1)) { - if(pToAdd.Type == .Text && _lastObject.Type == .Text) - { - _lastObject.Value.Text.Append(pToAdd.Data.Text); - return .Ok; - } - else if(_lastObject.Type == .Object) - { - _lastObject.Value.Object.Add(pToAdd.Data.Bofa.Name, pToAdd.Data.Bofa); - _lastObject._lastObject = pToAdd.Data.Bofa; - return .Ok; + if(pToAdd.Type == .Text && Type == .Text) + { + Value.Text.Append(scope $"\n{pToAdd.Data.Text}"); + return .Ok; + } + else if(Type == .Object) + { + if(Value.Object.ContainsKey(pToAdd.Data.Bofa.Name)) + return .Err; + Value.Object.Add(pToAdd.Data.Bofa.Name, pToAdd.Data.Bofa); + _lastObject = pToAdd.Data.Bofa; + return .Ok; - } - else if(_lastObject.Type == .Array) - { - _lastObject.Value.Array.Add(pToAdd.Data.Bofa); - _lastObject._lastObject = pToAdd.Data.Bofa; - return .Ok; - } + } + else if(Type == .Array) + { + Value.Array.Add(pToAdd.Data.Bofa); + _lastObject = pToAdd.Data.Bofa; + return .Ok; + } + return .Err; //Cannot insert here } //Can we even go deeper - if(!(_lastObject.Type == .Object || _lastObject.Type == .Array)) + if(_lastObject == null || !(_lastObject.Type == .Object || _lastObject.Type == .Array)) return .Err; pToAdd.Depth--; diff --git a/src/Testing/Default.bf b/src/Testing/Default.bf index 0510b75..977114a 100644 --- a/src/Testing/Default.bf +++ b/src/Testing/Default.bf @@ -6,24 +6,131 @@ using System.Collections; class Default { - [Test] - public static void Default_Test_1() + [Test(Name="Parsing all Types")] + public static void Parsing_1() { + String content = """ + l one line of text + b bool true + # saoidsaodsad t text goes here - Text addendum + n tone 12.5 + #husdhfiudshfds + bn biggie 65645645645.6 + i int 234345 + + + bi bint 38432847329847329 + o object + b content true + a array + b content true + b content true """; List output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); + Test.Assert(output.Count == 9); + Test.Assert(output[7].Value.Object.Count == 1); + Test.Assert(output[8].Value.Array.Count == 2); + Test.Assert(errors.Count == 0); + + DeleteContainerAndItems!(output); + delete errors; + } + + [Test(Name="Parsing Number")] + public static void Parsing_2() + { + + String content = """ + n number 1.0 + n number_1 345 + bn bignumber 2132432432.56564 + i integer 21324 + bi biginteger 565765765765765 + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + + Test.Assert(output.Count == 5); + Test.Assert(errors.Count == 0); + + DeleteContainerAndItems!(output); + delete errors; + } + + [Test(Name="Parsing Multiline Text")] + public static void Parsing_3() + { + + String content = """ + t Multiline text + - several lines + - can be added to a single thing + - this does mean + - that stuff has to be appended + - but thats fine + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + + Test.Assert(output.Count == 1); + Test.Assert(errors.Count == 0); + + DeleteContainerAndItems!(output); + delete errors; + } + + [Test(Name="Parsing Objects")] + public static void Parsing_4() + { + + String content = """ + o object + n member 1 + b other true + o obj + o deeper + o even deeper + n member 1 + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + Test.Assert(output.Count == 2); + Test.Assert(errors.Count == 0); + DeleteContainerAndItems!(output); + delete errors; + } + [Test(Name="Parsing Dublicate Key")] + public static void Parsing_5() + { + String content = """ + n number 1 + n number 2 + o obj + n member 1 + n member 2 + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + + Test.Assert(output.Count == 2); + Test.Assert(errors.Count == 2); DeleteContainerAndItems!(output); delete errors; diff --git a/src/Testing/Profiling.bf b/src/Testing/Profiling.bf new file mode 100644 index 0000000..1ace203 --- /dev/null +++ b/src/Testing/Profiling.bf @@ -0,0 +1,5 @@ +namespace Bofa.Testing; + +class Profiling +{ +} \ No newline at end of file From 73ba086c54d7b2a3dce4bfe86fee1a204578f1d7 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Wed, 14 Aug 2024 21:46:36 +0200 Subject: [PATCH 13/22] added testing + some performance improvements --- BeefProj.toml | 1 - BeefSpace.toml | 4 ++ src/BofaParser.bf | 10 +++- src/Program.bf | 39 ++++++++++++++ src/Testing/Profiling.bf | 110 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/Program.bf diff --git a/BeefProj.toml b/BeefProj.toml index 0d15fdc..ddfd45a 100644 --- a/BeefProj.toml +++ b/BeefProj.toml @@ -2,5 +2,4 @@ FileVersion = 1 [Project] Name = "Bofa" -TargetType = "BeefLib" StartupObject = "Bofa.Program" diff --git a/BeefSpace.toml b/BeefSpace.toml index ba54fc1..9edf396 100644 --- a/BeefSpace.toml +++ b/BeefSpace.toml @@ -6,3 +6,7 @@ StartupProject = "Bofa" [Configs.Test.Win64] LargeStrings = true + +[Configs.Debug.Win64] +LargeStrings = true +LargeCollections = true diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 85b36d8..6de49d2 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -2,6 +2,7 @@ namespace Bofa; using System; using System.IO; +using System.Security.Cryptography; using System.Collections; using Bofa.Parser; @@ -17,6 +18,10 @@ class BofaParser public static void Parse(Stream pToParse, List pResult, List pErrors) { + HashSet lowLevelObjects = new .(100); + defer delete lowLevelObjects; + + if (pToParse == null || pResult == null) { //Cannot parse what doesnt exist pErrors.Add(-1); @@ -52,8 +57,10 @@ class BofaParser //If we are on the lowest level we can just add them here if(entry.Depth == 0 && entry.Type ==.Bofa) { - if(pResult.FindIndex(scope (x) => { return x.Name == entry.Data.Bofa.Name;}) < 0) + if(lowLevelObjects.Add(SHA256.Hash(cast!>(entry.Data.Bofa.Name)))) + { pResult.Add(entry.Data.Bofa); + } else { pErrors.Add(entry.Line); //Dublicate name error @@ -305,4 +312,5 @@ class BofaParser } return (.(pLine, 0, (i < pLine.Length) ? i - 1 : i), .(pLine, i)); } + } \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf new file mode 100644 index 0000000..efd7a93 --- /dev/null +++ b/src/Program.bf @@ -0,0 +1,39 @@ +using System; + +namespace Bofa +{ + + class Program + { + public static void Main() + { + Bofa.Testing.Profiling.Profiling_Normal_Large(); + } + } +} + + + +namespace System.Security.Cryptography +{ + extension SHA256Hash : IHashable + { + public int GetHashCode() + { + return this.mHash[0]; + } + } + + +} + +namespace System +{ + static + { + public static mixin cast(var v) + { + *(T*)(void*)&v + } + } +} \ No newline at end of file diff --git a/src/Testing/Profiling.bf b/src/Testing/Profiling.bf index 1ace203..265aba2 100644 --- a/src/Testing/Profiling.bf +++ b/src/Testing/Profiling.bf @@ -1,5 +1,115 @@ namespace Bofa.Testing; +using Bofa; + +using System; +using System.Collections; + class Profiling { + [Test(Name = "Profiling: normal 1000 * 15")] + public static void Profiling_Normal() + { + for (int i < 1000) + { + String content = """ + l one line of text + b bool true + # saoidsaodsad + t text goes here + - Text addendum + n tone 12.5 + #husdhfiudshfds + bn biggie 65645645645.6 + i int 234345 + + + bi bint 38432847329847329 + o object + b content true + a array + b content true + b content true + """; + List output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + DeleteContainerAndItems!(output); + delete errors; + } + } + + [Test(Name = "Profiling: normal 10 * 1500")] + public static void Profiling_Normal_Medium() + { + for (int i < 10) + { + String toParse = new .(10 * 1500); + for (int ii < 100) + { + toParse.Append(scope $""" + l one{ii} line of text + b bool{ii} true + # saoidsaodsad + t text{ii} goes here + - Text addendum + n tone{ii} 12.5 + #husdhfiudshfds + bn biggie{ii} 65645645645.6 + i int{ii} 234345 + + + bi bint{ii} 38432847329847329 + o object{ii} + b content true + a array{ii} + b content true + b content true + """); + } + List output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteContainerAndItems!(output); + delete errors; + delete toParse; + } + } + + + + [Test(Name = "Profiling: normal 1 * 150000")] + public static void Profiling_Normal_Large() + { + String toParse = new .(10 * 150000); + for (int ii < 10000) + { + toParse.Append(scope $""" + l one{ii} line of text + b bool{ii} true + # saoidsaodsad + t text{ii} goes here + - Text addendum + n tone{ii} 12.5 + #husdhfiudshfds + bn biggie{ii} 65645645645.6 + i int{ii} 234345 + + + bi bint{ii} 38432847329847329 + o object{ii} + b content true + a array{ii} + b content true + b content true + + """); + } + List output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteContainerAndItems!(output); + delete errors; + delete toParse; + } } \ No newline at end of file From 176de85a210de44c0763d5b3815add9aa9743666 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Wed, 14 Aug 2024 22:08:04 +0200 Subject: [PATCH 14/22] some changes --- src/BofaParser.bf | 1 - src/Testing/Profiling.bf | 40 ++++++++++++++++++++-------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 6de49d2..57db108 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -21,7 +21,6 @@ class BofaParser HashSet lowLevelObjects = new .(100); defer delete lowLevelObjects; - if (pToParse == null || pResult == null) { //Cannot parse what doesnt exist pErrors.Add(-1); diff --git a/src/Testing/Profiling.bf b/src/Testing/Profiling.bf index 265aba2..ca906ae 100644 --- a/src/Testing/Profiling.bf +++ b/src/Testing/Profiling.bf @@ -13,24 +13,23 @@ class Profiling for (int i < 1000) { String content = """ - l one line of text - b bool true - # saoidsaodsad - t text goes here - - Text addendum - n tone 12.5 - #husdhfiudshfds - bn biggie 65645645645.6 - i int 234345 +l one line of text +b bool true +# saoidsaodsad +t text goes here +- Text addendum +n tone 12.5 +#husdhfiudshfds +bn biggie 65645645645.6 +i int 234345 +bi bint 38432847329847329 +o object +b content true +a array +b content true +b content true - - bi bint 38432847329847329 - o object - b content true - a array - b content true - b content true - """; +"""; List output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); @@ -65,6 +64,7 @@ class Profiling a array{ii} b content true b content true + """); } List output = new .(); @@ -76,13 +76,13 @@ class Profiling } } - - [Test(Name = "Profiling: normal 1 * 150000")] + + [Test(Name = "Profiling: normal 1 * 600000")] public static void Profiling_Normal_Large() { String toParse = new .(10 * 150000); - for (int ii < 10000) + for (int ii < 40000) { toParse.Append(scope $""" l one{ii} line of text From 11145e278bea9154c518bd21c839ac044cde3fbd Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Thu, 15 Aug 2024 20:01:16 +0200 Subject: [PATCH 15/22] more performance stuff, new tests, and toString implemented --- BeefProj.toml | 1 + src/Bofa.bf | 129 +++++++++++++++++++++++++++ src/BofaParser.bf | 31 +++---- src/Extension.bf | 10 +++ src/Parser/BofaParserInsert.bf | 36 ++++++++ src/Program.bf | 39 --------- src/Testing/Consistency.bf | 45 ++++++++++ src/Testing/Default.bf | 22 +++-- src/Testing/Fuzzing.bf | 45 ++++++++++ src/Testing/Profiling.bf | 155 +++++++++++++++++++++++++++------ 10 files changed, 421 insertions(+), 92 deletions(-) create mode 100644 src/Extension.bf delete mode 100644 src/Program.bf create mode 100644 src/Testing/Consistency.bf create mode 100644 src/Testing/Fuzzing.bf diff --git a/BeefProj.toml b/BeefProj.toml index ddfd45a..0d15fdc 100644 --- a/BeefProj.toml +++ b/BeefProj.toml @@ -2,4 +2,5 @@ FileVersion = 1 [Project] Name = "Bofa" +TargetType = "BeefLib" StartupObject = "Bofa.Program" diff --git a/src/Bofa.bf b/src/Bofa.bf index 8544b43..06c0b26 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -1,6 +1,7 @@ namespace Bofa; using System; +using System.Collections; class Bofa { @@ -12,6 +13,134 @@ class Bofa public StringView Typename; public BofaValue Value; + public override void ToString(String strBuffer) + { + int64 depth = 0; + Bofa target = this; + List<(int64, Bofa)> toProcess = new .(); + defer delete toProcess; + + repeat + { + + target.ToString(strBuffer, depth); + + if(target.Type == .Array) + { + depth++; + for(var i in Value.Array.Reversed) + toProcess.Add((depth, i)); + } + else if(target.Type == .Object) + { + depth++; + for(var i in Value.Object) + toProcess.Add((depth, i.value)); + } + + if(toProcess.IsEmpty) + target = null; + else + { + var t = toProcess.PopBack(); + depth = t.0; + target = t.1; + strBuffer.Append('\n'); + } + } while(target != null); + } + + private void ToString(String strBuffer, int64 pDepth) + { + strBuffer.Append(' ', pDepth); + switch(Type) + { + case .Array: + strBuffer.Append(scope $"a {Name}"); + case .BigInteger: + strBuffer.Append(scope $"bi {Name} {Value.BigInteger}"); + case .BigNumber: + strBuffer.Append(scope $"bn {Name} {Value.BigNumber}"); + case .Boolean: + strBuffer.Append(scope $"b {Name} {Value.Boolean ? "true" : "false"}"); + case .Custom: + strBuffer.Append(scope $"c {Typename} {Name} {Value.Custom}"); + case .Integer: + strBuffer.Append(scope $"i {Name} {Value.Integer}"); + case .Line: + strBuffer.Append(scope $"l {Name} {Value.Line}"); + case .Number: + strBuffer.Append(scope $"n {Name} {Value.Number}"); + case .Object: + strBuffer.Append(scope $"o {Name}"); + case .Text: + strBuffer.Append(scope $"t {Name} "); + for(var i in Value.Text.Split('\n', .None)) + { + strBuffer.Append(i); + if(@i.HasMore) + { + strBuffer.Append('\n'); + strBuffer.Append(' ', pDepth); + strBuffer.Append("- " ); + } + + } + } + } + + ///Deletes this object without filling the stack + public void DeepDeletion() + { + if(this.Type == .Array || this.Type == .Object) + { + List toDelete = new .(); + List toProcess = new .(); + + toDelete.Add(this); + Bofa target = this; + repeat + { + if(target.Type == .Object) + { + for(var i in target.Value.Object) + { + toDelete.Add(i.value); + toProcess.Add(i.value); + } + target.Value.Object.Clear(); + } + else if(target.Type == .Array) + { + for(var i in target.Value.Array) + { + toDelete.Add(i); + toProcess.Add(i); + } + target.Value.Array.Clear(); + } + + if(toProcess.Count > 0 && target != null) + target = toProcess.PopBack(); + else + target = null; + } while(target != null); + + for(var i in toDelete.Reversed) + delete i; + + delete toDelete; + delete toProcess; + } + else + { + if(_line != null) + delete _line; + if(Type == .Text) + delete Value.Text; + } + } + public ~this() { if(_line != null) diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 57db108..b8b7593 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -9,18 +9,16 @@ using Bofa.Parser; class BofaParser { - public static void Parse(StringView pToParse, List pResult, List pErrors) + public static void Parse(StringView pToParse, Dictionary pResult, List pErrors) { StringStream stream = new .(pToParse, .Reference); defer delete stream; Parse(stream, pResult, pErrors); } - public static void Parse(Stream pToParse, List pResult, List pErrors) + public static void Parse(Stream pToParse, Dictionary pResult, List pErrors) { - HashSet lowLevelObjects = new .(100); - defer delete lowLevelObjects; - + Bofa last = null; if (pToParse == null || pResult == null) { //Cannot parse what doesnt exist pErrors.Add(-1); @@ -36,6 +34,7 @@ class BofaParser String l = new .(); if (reader.ReadLine(l) case .Err) { //Despite data being here, we cannot read it + delete l; pErrors.Add(-2); return; } @@ -49,16 +48,18 @@ class BofaParser continue; } if(entry.Type == .Error) + { pErrors.Add(line); - if(entry.Type == .Text) - defer delete l; + continue; + } //If we are on the lowest level we can just add them here if(entry.Depth == 0 && entry.Type ==.Bofa) { - if(lowLevelObjects.Add(SHA256.Hash(cast!>(entry.Data.Bofa.Name)))) + if(!pResult.ContainsKey(entry.Data.Bofa.Name)) { - pResult.Add(entry.Data.Bofa); + last = entry.Data.Bofa; + pResult.Add(entry.Data.Bofa.Name, entry.Data.Bofa); } else { @@ -68,27 +69,29 @@ class BofaParser } else if(entry.Depth == 1 && entry.Type == .Text) { - if(pResult[pResult.Count-1].Type == .Text) - pResult[pResult.Count-1].Value.Text.Append(scope $"\n{entry.Data.Text}"); + if(last.Type == .Text) + last.Value.Text.Append(scope $"\n{entry.Data.Text}"); else pErrors.Add(entry.Line); //Bad text error } else { entry.Depth--; - if(pResult[pResult.Count-1].[Friend]_Insert(&entry) case .Err) + if(last.[Friend]_Insert(&entry) case .Err) { pErrors.Add(line); delete entry.Data.Bofa; } } - + if(entry.Type == .Text) + delete l; line++; } return; //Being done normally } + [Inline] private static ParserEntry ParseLine(String pLine, int64 pLineNumber) { StringView line = pLine; @@ -129,8 +132,6 @@ class BofaParser if (type.0 == "") //This should never be reached { Runtime.FatalError("Unreachable code reached"); - toReturn.Type = .Error; - return toReturn; } else if (type.0 == "-") { diff --git a/src/Extension.bf b/src/Extension.bf new file mode 100644 index 0000000..d0898b5 --- /dev/null +++ b/src/Extension.bf @@ -0,0 +1,10 @@ +namespace System +{ + static + { + public static mixin cast(var v) + { + *(T*)(void*)&v + } + } +} \ No newline at end of file diff --git a/src/Parser/BofaParserInsert.bf b/src/Parser/BofaParserInsert.bf index bbb6dc3..ffa18a2 100644 --- a/src/Parser/BofaParserInsert.bf +++ b/src/Parser/BofaParserInsert.bf @@ -6,8 +6,43 @@ using System; extension Bofa { + [Inline] private Result _Insert(ParserEntry* pToAdd) { + Bofa target = this; + while(!(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1))) + { + if(target == null || !(target.Type == .Object || target.Type == .Array)) + return .Err; + + pToAdd.Depth--; + target = target._lastObject; + } + + if(pToAdd.Type == .Text && target.Type == .Text) + { + target.Value.Text.Append(scope $"\n{pToAdd.Data.Text}"); + //delete pToAdd.Data.Text; + return .Ok; + } + else if(target.Type == .Object) + { + if(target.Value.Object.ContainsKey(pToAdd.Data.Bofa.Name)) + return .Err; + target.Value.Object.Add(pToAdd.Data.Bofa.Name, pToAdd.Data.Bofa); + target._lastObject = pToAdd.Data.Bofa; + return .Ok; + + } + else if(target.Type == .Array) + { + target.Value.Array.Add(pToAdd.Data.Bofa); + target._lastObject = pToAdd.Data.Bofa; + return .Ok; + } + return .Err; + + /* //See if we can insert and do so if(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1)) { @@ -41,5 +76,6 @@ extension Bofa pToAdd.Depth--; return _lastObject._Insert(pToAdd); + */ } } \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf deleted file mode 100644 index efd7a93..0000000 --- a/src/Program.bf +++ /dev/null @@ -1,39 +0,0 @@ -using System; - -namespace Bofa -{ - - class Program - { - public static void Main() - { - Bofa.Testing.Profiling.Profiling_Normal_Large(); - } - } -} - - - -namespace System.Security.Cryptography -{ - extension SHA256Hash : IHashable - { - public int GetHashCode() - { - return this.mHash[0]; - } - } - - -} - -namespace System -{ - static - { - public static mixin cast(var v) - { - *(T*)(void*)&v - } - } -} \ No newline at end of file diff --git a/src/Testing/Consistency.bf b/src/Testing/Consistency.bf new file mode 100644 index 0000000..9d2f1ed --- /dev/null +++ b/src/Testing/Consistency.bf @@ -0,0 +1,45 @@ +namespace Bofa.Testing; + +using Bofa; + +using System; +using System.Collections; + +class Consistency +{ + [Test(Name="Reverse simple")] + public static void Standart() + { + String content = """ + l one line of text + b bool true + t textgoes here + - Text addendum + n tone 12.5 + bn biggie 6.56456e+10 + i int 234345 + bi bint 38432847329847329 + o object + b content true + a array + b content true + b content true + """; + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(content, output, errors); + + String s = scope .(); + for(var i in output) + { + i.value.ToString(s); + s.Append('\n'); + } + s.RemoveFromEnd(1); + + Test.Assert(content == s); + + DeleteDictionaryAndValues!(output); + delete errors; + } +} \ No newline at end of file diff --git a/src/Testing/Default.bf b/src/Testing/Default.bf index 977114a..9b708c7 100644 --- a/src/Testing/Default.bf +++ b/src/Testing/Default.bf @@ -29,16 +29,14 @@ class Default b content true b content true """; - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); Test.Assert(output.Count == 9); - Test.Assert(output[7].Value.Object.Count == 1); - Test.Assert(output[8].Value.Array.Count == 2); Test.Assert(errors.Count == 0); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; } @@ -53,14 +51,14 @@ class Default i integer 21324 bi biginteger 565765765765765 """; - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); Test.Assert(output.Count == 5); Test.Assert(errors.Count == 0); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; } @@ -76,14 +74,14 @@ class Default - that stuff has to be appended - but thats fine """; - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); Test.Assert(output.Count == 1); Test.Assert(errors.Count == 0); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; } @@ -102,14 +100,14 @@ class Default o even deeper n member 1 """; - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); Test.Assert(output.Count == 2); Test.Assert(errors.Count == 0); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; } @@ -125,14 +123,14 @@ class Default n member 1 n member 2 """; - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(content, output, errors); Test.Assert(output.Count == 2); Test.Assert(errors.Count == 2); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; } } \ No newline at end of file diff --git a/src/Testing/Fuzzing.bf b/src/Testing/Fuzzing.bf new file mode 100644 index 0000000..4374964 --- /dev/null +++ b/src/Testing/Fuzzing.bf @@ -0,0 +1,45 @@ +namespace Bofa.Testing; + +using Bofa; + +using System; +using System.Collections; + +class Fuzzing +{ + [Test(Name = "Fuzzing - 10 * 1000000 random characters")] + public static void Fuzzin_Random() + { + for (int i < 10) + { + String toParse = new .(10 * 1500); + for (int ii < 250000) + toParse.Append(cast!(gRand.NextI32())); + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + delete toParse; + } + } + + [Test(Name = "Fuzzing - 10 * 10000000 random characters")] + public static void Fuzzin_Random_Large() + { + for (int i < 10) + { + String toParse = new .(10 * 1500); + for (int ii < 2500000) + toParse.Append(cast!(gRand.NextI32())); + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + delete toParse; + } + } +} \ No newline at end of file diff --git a/src/Testing/Profiling.bf b/src/Testing/Profiling.bf index ca906ae..f7ebcd0 100644 --- a/src/Testing/Profiling.bf +++ b/src/Testing/Profiling.bf @@ -12,28 +12,32 @@ class Profiling { for (int i < 1000) { - String content = """ -l one line of text -b bool true -# saoidsaodsad -t text goes here -- Text addendum -n tone 12.5 -#husdhfiudshfds -bn biggie 65645645645.6 -i int 234345 -bi bint 38432847329847329 -o object -b content true -a array -b content true -b content true + String toParse = scope .(); + toParse.Append(scope $""" + l one line of text + b bool true + # saoidsaodsad + t text goes here + - Text addendum + n tone 12.5 + #husdhfiudshfds + bn biggie 65645645645.6 + i int 234345 + bi bint 38432847329847329 + o object + b content true + a array + b content true + b content true -"""; - List output = new .(); + """); + + + + Dictionary output = new .(); List errors = new .(); - BofaParser.Parse(content, output, errors); - DeleteContainerAndItems!(output); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); delete errors; } } @@ -67,10 +71,10 @@ b content true """); } - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(toParse, output, errors); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; delete toParse; } @@ -78,11 +82,11 @@ b content true - [Test(Name = "Profiling: normal 1 * 600000")] + [Test(Name = "Profiling: normal 1 * 300000")] public static void Profiling_Normal_Large() { String toParse = new .(10 * 150000); - for (int ii < 40000) + for (int ii < 20000) { toParse.Append(scope $""" l one{ii} line of text @@ -105,11 +109,110 @@ b content true """); } - List output = new .(); + Dictionary output = new .(); List errors = new .(); BofaParser.Parse(toParse, output, errors); - DeleteContainerAndItems!(output); + DeleteDictionaryAndValues!(output); delete errors; delete toParse; } + + [Test(Name = "Profiling: Depth testing 100 * 100")] + public static void Profiling_Depth_Testing() + { + for (int i < 100) + { + String toParse = scope .(); + for(int ii < 100) + { + toParse.Append(' ', ii); + toParse.Append(scope $"o obj\n"); + } + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + } + } + [Test(Name = "Profiling: Depth testing 100 * 1000")] + public static void Profiling_Depth_Testing_Medium() + { + for (int i < 100) + { + String toParse = scope .(); + for(int ii < 1000) + { + toParse.Append(' ', ii); + toParse.Append(scope $"o obj\n"); + } + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + } + } + + [Test(Name = "Profiling: Depth testing 10 * 5000")] + public static void Profiling_Depth_Testing_Large() + { + for (int i < 10) + { + String toParse = scope .(); + for(int ii < 5000) + { + toParse.Append(' ', ii); + toParse.Append(scope $"o obj\n"); + } + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + output["obj"].DeepDeletion(); + delete output; + delete errors; + } + } + + [Test(Name = "Profiling: Texts 10 * 1000")] + public static void Profiling_Texts() + { + for (int i < 10) + { + String toParse = new .(10 * 1500); + toParse.Append("t text goes here"); + for (int ii < 1000) + toParse.Append("- Addendum"); + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + delete toParse; + } + } + + [Test(Name = "Profiling: Large Texts 10 * 100000")] + public static void Profiling_Texts_Large() + { + for (int i < 10) + { + String toParse = new .(10 * 1500); + toParse.Append("t text goes here"); + for (int ii < 100000) + toParse.Append("- Addendum"); + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(toParse, output, errors); + DeleteDictionaryAndValues!(output); + delete errors; + delete toParse; + } + } + } \ No newline at end of file From 0da1c14ed75c0f4559aa03b66b947351a273131b Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Fri, 16 Aug 2024 11:49:00 +0200 Subject: [PATCH 16/22] basic access --- src/Bofa.bf | 35 +++++++++++++++++++++++++++++++++-- src/Testing/Consistency.bf | 4 ++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Bofa.bf b/src/Bofa.bf index 06c0b26..55ae41b 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -60,7 +60,7 @@ class Bofa case .BigInteger: strBuffer.Append(scope $"bi {Name} {Value.BigInteger}"); case .BigNumber: - strBuffer.Append(scope $"bn {Name} {Value.BigNumber}"); + strBuffer.Append(scope $"bn {Name} {Value.BigNumber:R}"); case .Boolean: strBuffer.Append(scope $"b {Name} {Value.Boolean ? "true" : "false"}"); case .Custom: @@ -70,7 +70,7 @@ class Bofa case .Line: strBuffer.Append(scope $"l {Name} {Value.Line}"); case .Number: - strBuffer.Append(scope $"n {Name} {Value.Number}"); + strBuffer.Append(scope $"n {Name} {Value.Number:R}"); case .Object: strBuffer.Append(scope $"o {Name}"); case .Text: @@ -152,4 +152,35 @@ class Bofa else if(Type == .Array) DeleteContainerAndItems!(Value.Array); } + + public ref Bofa this[StringView view] + { + [Checked] + get + { + Runtime.Assert(Type == .Object); + Runtime.Assert(Value.Object.ContainsKey(view)); + return ref Value.Object[view]; + } + + [Unchecked, Inline] + get + { + return ref Value.Object[view]; + } + + [Checked] + set + { + Runtime.Assert(Type == .Object); + Runtime.Assert(!Value.Object.ContainsKey(view)); + Value.Object[view] = value; + } + + [Unchecked, Inline] + set + { + Value.Object[view] = value; + } + } } \ No newline at end of file diff --git a/src/Testing/Consistency.bf b/src/Testing/Consistency.bf index 9d2f1ed..6541d4d 100644 --- a/src/Testing/Consistency.bf +++ b/src/Testing/Consistency.bf @@ -16,7 +16,7 @@ class Consistency t textgoes here - Text addendum n tone 12.5 - bn biggie 6.56456e+10 + bn biggie 65645654535.553001 i int 234345 bi bint 38432847329847329 o object @@ -32,7 +32,7 @@ class Consistency String s = scope .(); for(var i in output) { - i.value.ToString(s); + i.value.ToString(s); s.Append('\n'); } s.RemoveFromEnd(1); From 501a4af63687980f1760133e3e98bf4aac75106a Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Fri, 23 Aug 2024 21:25:13 +0200 Subject: [PATCH 17/22] trying to debug stuff --- BeefProj.toml | 1 - src/Bofa.bf | 66 +++++- src/BofaParser.bf | 212 ++++++++++---------- src/Extension.bf | 21 ++ src/Program.bf | 20 ++ src/Serialization/BofaIncludeAttribute.bf | 13 ++ src/Serialization/BofaSerializeAttribute.bf | 112 +++++++++++ src/Serialization/IBofaParseable.bf | 11 + src/Testing/Fuzzing.bf | 4 +- src/Testing/Serialization.bf | 25 +++ 10 files changed, 375 insertions(+), 110 deletions(-) create mode 100644 src/Program.bf create mode 100644 src/Serialization/BofaIncludeAttribute.bf create mode 100644 src/Serialization/BofaSerializeAttribute.bf create mode 100644 src/Serialization/IBofaParseable.bf create mode 100644 src/Testing/Serialization.bf diff --git a/BeefProj.toml b/BeefProj.toml index 0d15fdc..ddfd45a 100644 --- a/BeefProj.toml +++ b/BeefProj.toml @@ -2,5 +2,4 @@ FileVersion = 1 [Project] Name = "Bofa" -TargetType = "BeefLib" StartupObject = "Bofa.Program" diff --git a/src/Bofa.bf b/src/Bofa.bf index 55ae41b..324cd46 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -5,7 +5,18 @@ using System.Collections; class Bofa { - private String _line = null; //The actual line + private String __line = null; //The actual line + private String _line + { + get + { + return __line; + } + set + { + __line = value; + } + } private Bofa _lastObject = null; //If we are a container we keep track of the last container inside of us public StringView Name; @@ -136,11 +147,13 @@ class Bofa { if(_line != null) delete _line; + if(Type == .Text) delete Value.Text; } } + public ~this() { if(_line != null) @@ -183,4 +196,55 @@ class Bofa Value.Object[view] = value; } } + + public ref Bofa this[int view] + { + [Checked] + get + { + Runtime.Assert(Type == .Array); + Runtime.Assert(Value.Array.Count > view); + return ref Value.Array[view]; + } + + [Unchecked, Inline] + get + { + return ref Value.Array[view]; + } + + [Checked] + set + { + Runtime.Assert(Type == .Array); + Runtime.Assert(Value.Array.Count > view); + Value.Array[view] = value; + } + + [Unchecked, Inline] + set + { + Value.Array[view] = value; + } + } + + ///Get the value if the object is a container + public Result Get(StringView pKey) + { + if(Type != .Object) + return .Err; + if(!Value.Object.ContainsKey(pKey)) + return .Err; + return Value.Object[pKey]; + } + + ///Get the value if the object is a container + public Result Get(int pIndex) + { + if(Type != .Array) + return .Err; + if(!(Value.Array.Count > pIndex)) + return .Err; + return Value.Array[pIndex]; + } } \ No newline at end of file diff --git a/src/BofaParser.bf b/src/BofaParser.bf index b8b7593..3517bf9 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -32,31 +32,32 @@ class BofaParser while (reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you { String l = new .(); + if (reader.ReadLine(l) case .Err) { //Despite data being here, we cannot read it delete l; pErrors.Add(-2); return; } - + var entry = ParseLine(l, line); - if(!(entry.Type == .Bofa || entry.Type == .Text)) + if (!(entry.Type == .Bofa || entry.Type == .Text)) delete l; //In these cases we have no useable data - if(entry.Type == .Empty) + if (entry.Type == .Empty) { line++; continue; } - if(entry.Type == .Error) + if (entry.Type == .Error) { pErrors.Add(line); continue; } //If we are on the lowest level we can just add them here - if(entry.Depth == 0 && entry.Type ==.Bofa) + if (entry.Depth == 0 && entry.Type == .Bofa) { - if(!pResult.ContainsKey(entry.Data.Bofa.Name)) + if (!pResult.ContainsKey(entry.Data.Bofa.Name)) { last = entry.Data.Bofa; pResult.Add(entry.Data.Bofa.Name, entry.Data.Bofa); @@ -67,27 +68,27 @@ class BofaParser delete entry.Data.Bofa; } } - else if(entry.Depth == 1 && entry.Type == .Text) + else if (entry.Depth == 1 && entry.Type == .Text) { - if(last.Type == .Text) + if (last.Type == .Text) last.Value.Text.Append(scope $"\n{entry.Data.Text}"); else - pErrors.Add(entry.Line); //Bad text error + pErrors.Add(entry.Line); //Bad text error + delete l; } else { entry.Depth--; - if(last.[Friend]_Insert(&entry) case .Err) + if (last.[Friend]_Insert(&entry) case .Err) { pErrors.Add(line); delete entry.Data.Bofa; } + else if (entry.Type == .Text) + delete l; } - if(entry.Type == .Text) - delete l; line++; } - return; //Being done normally } @@ -139,42 +140,41 @@ class BofaParser toReturn.Data.Text = line; toReturn.Depth = depth + 1; return toReturn; - } //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 == "") - { //Its of type custom but ends after the custom - toReturn.Type = .Error; - return toReturn; - } - 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: + case "c": + let tnameres = NextPart(line); + if (tnameres.0 == "") + { //Its of type custom but ends after the custom toReturn.Type = .Error; - return toReturn; //Unsupported type error + return toReturn; + } + 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: + toReturn.Type = .Error; + return toReturn; //Unsupported type error } #endregion @@ -215,77 +215,77 @@ class BofaParser { toReturn.Type = .Error; return toReturn; - } + } Bofa bofaRes = new .(); bofaRes.Name = nameres.0; bofaRes.Typename = typeName; switch (type.0) { - case "n": - bofaRes.Type = .Number; - var result = float.Parse(line); - if (result case .Err) - { - delete bofaRes; - toReturn.Type = .Error; - return toReturn; - } - bofaRes.Value.Number = result.Value; - case "b": - if (line == "true") - bofaRes.Value.Boolean = true; - else if (line == "false") - bofaRes.Value.Boolean = false; - else - { - delete bofaRes; - toReturn.Type = .Error; - return toReturn; - } - bofaRes.Type = .Boolean; - case "l": - bofaRes.Value.Line = line; - bofaRes.Type = .Line; - case "bn": - bofaRes.Type = .BigNumber; - var result = double.Parse(line); - if (result case .Err) - { - delete bofaRes; - toReturn.Type = .Error; - return toReturn; - } - bofaRes.Value.BigNumber = result.Value; - case "i": - bofaRes.Type = .Integer; - var result = int32.Parse(line); - if (result case .Err) - { - delete bofaRes; - toReturn.Type = .Error; - return toReturn; - } - bofaRes.Value.Integer = result.Value; - case "bi": - bofaRes.Type = .BigInteger; - var result = int64.Parse(line); - if (result case .Err) - { - delete bofaRes; - toReturn.Type = .Error; - return toReturn; - } - bofaRes.Value.BigInteger = result.Value; - case "t": - bofaRes.Value.Text = new String(line); - bofaRes.Type = .Text; - case "c": - bofaRes.Value.Custom = line; - bofaRes.Type = .Custom; - default: //Unknown type + case "n": + bofaRes.Type = .Number; + var result = float.Parse(line); + if (result case .Err) + { delete bofaRes; toReturn.Type = .Error; return toReturn; + } + bofaRes.Value.Number = result.Value; + case "b": + if (line == "true") + bofaRes.Value.Boolean = true; + else if (line == "false") + bofaRes.Value.Boolean = false; + else + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Type = .Boolean; + case "l": + bofaRes.Value.Line = line; + bofaRes.Type = .Line; + case "bn": + bofaRes.Type = .BigNumber; + var result = double.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.BigNumber = result.Value; + case "i": + bofaRes.Type = .Integer; + var result = int32.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.Integer = result.Value; + case "bi": + bofaRes.Type = .BigInteger; + var result = int64.Parse(line); + if (result case .Err) + { + delete bofaRes; + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.BigInteger = result.Value; + case "t": + bofaRes.Value.Text = new String(line); + bofaRes.Type = .Text; + case "c": + bofaRes.Value.Custom = line; + bofaRes.Type = .Custom; + default: //Unknown type + delete bofaRes; + toReturn.Type = .Error; + return toReturn; } #endregion //If this ever returns something went wrong diff --git a/src/Extension.bf b/src/Extension.bf index d0898b5..bacdd8c 100644 --- a/src/Extension.bf +++ b/src/Extension.bf @@ -1,3 +1,5 @@ +using Bofa.Serialization; + namespace System { static @@ -7,4 +9,23 @@ namespace System *(T*)(void*)&v } } + + extension Int : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Integer; + pTarget.Typename = "Integer"; + pTarget.Value.Integer = (.)this; + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .Integer) + return false; + this = (.)pInput.Value.Integer; + return true; + } + } } \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf new file mode 100644 index 0000000..33ef40b --- /dev/null +++ b/src/Program.bf @@ -0,0 +1,20 @@ +namespace Bofa; + +using System; +using System.Collections; + +class Program +{ + + public static void Main() + { + + Bofa.Testing.Profiling.Profiling_Depth_Testing(); + Bofa.Testing.Profiling.Profiling_Depth_Testing_Medium(); + Bofa.Testing.Profiling.Profiling_Normal(); + Bofa.Testing.Profiling.Profiling_Normal_Medium(); + Bofa.Testing.Profiling.Profiling_Normal_Large(); + Bofa.Testing.Profiling.Profiling_Texts(); + Bofa.Testing.Profiling.Profiling_Texts_Large(); + } +} \ No newline at end of file diff --git a/src/Serialization/BofaIncludeAttribute.bf b/src/Serialization/BofaIncludeAttribute.bf new file mode 100644 index 0000000..515a068 --- /dev/null +++ b/src/Serialization/BofaIncludeAttribute.bf @@ -0,0 +1,13 @@ +namespace Bofa.Serialization; + +using System; + +struct BofaIncludeAttribute : Attribute +{ + public StringView Name; + + public this(StringView pName) + { + Name = pName; + } +} \ No newline at end of file diff --git a/src/Serialization/BofaSerializeAttribute.bf b/src/Serialization/BofaSerializeAttribute.bf new file mode 100644 index 0000000..c3a17f6 --- /dev/null +++ b/src/Serialization/BofaSerializeAttribute.bf @@ -0,0 +1,112 @@ +namespace Bofa.Serialization; + +using System; +using System.Reflection; + +using Bofa; + +[AttributeUsage(.Struct | .Class)] +struct BofaSerializeAttribute : Attribute, IOnTypeInit +{ + [Comptime] + public void OnTypeInit(Type type, Self* prev) + { + String serializeString = scope .("public bool Serialize(Bofa b)\n{\n"); + String deserializeString = scope .("public bool Deserialize(Bofa b)\n{\n"); + + serializeString.Append(""" + b.Type = .Object; + b.Value.Object = new .(); + b.Typename = "Object"; + Bofa toAdd; + + """); + + deserializeString.Append(""" + if(b.Type != .Object) + return false; + + """); + + + var fields = type.GetFields(); + for(var f in fields) + { + if(!f.IsPublic && !f.HasCustomAttribute()) + continue; + + bool hasIFace = false; + for(var i in f.FieldType.Interfaces) + if(i == typeof(IBofaParseable)) + hasIFace = true; + + //Hardcoded stuff + if(f.FieldType == typeof(int)) + hasIFace = true; + else if(f.FieldType == typeof(int8)) + hasIFace = true; + else if(f.FieldType == typeof(int16)) + hasIFace = true; + else if(f.FieldType == typeof(int32)) + hasIFace = true; + else if(f.FieldType == typeof(int64)) + hasIFace = true; + else if(f.FieldType == typeof(uint)) + hasIFace = true; + else if(f.FieldType == typeof(uint8)) + hasIFace = true; + else if(f.FieldType == typeof(uint16)) + hasIFace = true; + else if(f.FieldType == typeof(uint32)) + hasIFace = true; + else if(f.FieldType == typeof(uint64)) + hasIFace = true; + else if(f.FieldType == typeof(char8)) + hasIFace = true; + else if(f.FieldType == typeof(char16)) + hasIFace = true; + else if(f.FieldType == typeof(char32)) + hasIFace = true; + else if(f.FieldType == typeof(float)) + hasIFace = true; + else if(f.FieldType == typeof(double)) + hasIFace = true; + + if(!hasIFace) + continue; + + + StringView name; + name = f.Name; + if(f.HasCustomAttribute() && f.GetCustomAttribute() case .Ok(let attr)) + name = attr.Name; + + serializeString.Append(scope $""" + toAdd = new .(); + toAdd.Name = "{name}"; + if(!{f.Name}.Serialize(toAdd)) + \{ + delete toAdd; + return false; + \} + else + b.Value.Object.Add("{name}", toAdd); + """); + + deserializeString.Append(scope $""" + if(!b.Value.Object.ContainsKey("{name}")) + return false; + if(!{f.Name}.Deserialize(b.Value.Object["{name}"])) + return false; + """); + + } + + + serializeString.Append("\n\treturn true;\n}\n"); + deserializeString.Append("\n\treturn true;\n}\n"); + Compiler.EmitTypeBody(type, serializeString); + Compiler.EmitTypeBody(type, deserializeString); + Compiler.EmitAddInterface(type, typeof(IBofaParseable)); + } +} \ No newline at end of file diff --git a/src/Serialization/IBofaParseable.bf b/src/Serialization/IBofaParseable.bf new file mode 100644 index 0000000..9cd8314 --- /dev/null +++ b/src/Serialization/IBofaParseable.bf @@ -0,0 +1,11 @@ +namespace Bofa.Serialization; + +using System; + +interface IBofaParseable +{ + ///Serializes the current state of a bofa object, may allocate subobjects to fill + public bool Serialize(Bofa pTarget) mut; + ///Attempt to restore an object from the bofa input state + public bool Deserialize(Bofa pInput) mut; +} \ No newline at end of file diff --git a/src/Testing/Fuzzing.bf b/src/Testing/Fuzzing.bf index 4374964..08ddd0a 100644 --- a/src/Testing/Fuzzing.bf +++ b/src/Testing/Fuzzing.bf @@ -7,7 +7,7 @@ using System.Collections; class Fuzzing { - [Test(Name = "Fuzzing - 10 * 1000000 random characters")] + //[Test(Name = "Fuzzing - 10 * 1000000 random characters")] public static void Fuzzin_Random() { for (int i < 10) @@ -25,7 +25,7 @@ class Fuzzing } } - [Test(Name = "Fuzzing - 10 * 10000000 random characters")] + //[Test(Name = "Fuzzing - 10 * 10000000 random characters")] public static void Fuzzin_Random_Large() { for (int i < 10) diff --git a/src/Testing/Serialization.bf b/src/Testing/Serialization.bf new file mode 100644 index 0000000..6baaa0a --- /dev/null +++ b/src/Testing/Serialization.bf @@ -0,0 +1,25 @@ +namespace Bofa.Testing; + +using System; + +using Bofa; +using Bofa.Serialization; + +[BofaSerialize] +class Serialization +{ + public int anInteger = (.)1; + + [Test] + public static void Test() + { + Serialization s = scope .(); + Bofa b = scope .(); + b.Name = "s"; + s.Serialize(b); + + Console.WriteLine(b.ToString(.. scope .())); + //Console.Read(); + } + +} \ No newline at end of file From c0b09a47e6384f137b51c4467d96a8601a7466bc Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Sat, 24 Aug 2024 00:02:05 +0200 Subject: [PATCH 18/22] more leakchecking --- src/Bofa.bf | 16 ++-------------- src/BofaParser.bf | 34 +++++++++++++++++----------------- src/Parser/BofaParserInsert.bf | 3 +-- src/Parser/ParserEntryUnion.bf | 2 +- src/Program.bf | 17 +++++++++-------- src/Testing/Profiling.bf | 3 ++- 6 files changed, 32 insertions(+), 43 deletions(-) diff --git a/src/Bofa.bf b/src/Bofa.bf index 324cd46..779fd58 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -5,18 +5,8 @@ using System.Collections; class Bofa { - private String __line = null; //The actual line - private String _line - { - get - { - return __line; - } - set - { - __line = value; - } - } + + private String _line = null ~ if(_ != null) delete _; //The actual line private Bofa _lastObject = null; //If we are a container we keep track of the last container inside of us public StringView Name; @@ -156,8 +146,6 @@ class Bofa public ~this() { - if(_line != null) - delete _line; if(Type == .Text) delete Value.Text; else if(Type == .Object) diff --git a/src/BofaParser.bf b/src/BofaParser.bf index 3517bf9..ab8272c 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -6,6 +6,7 @@ using System.Security.Cryptography; using System.Collections; using Bofa.Parser; +using Bofa; class BofaParser { @@ -31,8 +32,7 @@ class BofaParser int64 line = 1; while (reader.Peek() case .Ok) //This might technically cause an issue when there is data added to the stream while we where busy processing, but if you hook this up to a network stream you deserve this happening to you { - String l = new .(); - + String l = new String(); if (reader.ReadLine(l) case .Err) { //Despite data being here, we cannot read it delete l; @@ -50,6 +50,8 @@ class BofaParser } if (entry.Type == .Error) { + if(entry.Data.Bofa != null) + delete entry.Data.Bofa; pErrors.Add(line); continue; } @@ -193,19 +195,20 @@ class BofaParser Bofa bofaRes = new Bofa(); bofaRes.[Friend]_line = pLine; bofaRes.Name = nameres.0; + toReturn.Type = .Bofa; + toReturn.Data.Bofa = bofaRes; bofaRes.Typename = typeName; if (type.0 == "o") { bofaRes.Type = .Object; bofaRes.Value.Object = new .(); - toReturn.Type = .Bofa; - toReturn.Data.Bofa = bofaRes; - return toReturn; } - bofaRes.Type = .Array; - bofaRes.Value.Array = new .(); - toReturn.Type = .Bofa; - toReturn.Data.Bofa = bofaRes; + else + { + bofaRes.Type = .Array; + bofaRes.Value.Array = new .(); + } + return toReturn; } #endregion @@ -219,6 +222,11 @@ class BofaParser Bofa bofaRes = new .(); bofaRes.Name = nameres.0; bofaRes.Typename = typeName; + + toReturn.Data.Bofa = bofaRes; + bofaRes.[Friend]_line = pLine; + + switch (type.0) { case "n": @@ -226,7 +234,6 @@ class BofaParser var result = float.Parse(line); if (result case .Err) { - delete bofaRes; toReturn.Type = .Error; return toReturn; } @@ -238,7 +245,6 @@ class BofaParser bofaRes.Value.Boolean = false; else { - delete bofaRes; toReturn.Type = .Error; return toReturn; } @@ -251,7 +257,6 @@ class BofaParser var result = double.Parse(line); if (result case .Err) { - delete bofaRes; toReturn.Type = .Error; return toReturn; } @@ -261,7 +266,6 @@ class BofaParser var result = int32.Parse(line); if (result case .Err) { - delete bofaRes; toReturn.Type = .Error; return toReturn; } @@ -271,7 +275,6 @@ class BofaParser var result = int64.Parse(line); if (result case .Err) { - delete bofaRes; toReturn.Type = .Error; return toReturn; } @@ -283,15 +286,12 @@ class BofaParser bofaRes.Value.Custom = line; bofaRes.Type = .Custom; default: //Unknown type - delete bofaRes; toReturn.Type = .Error; return toReturn; } #endregion //If this ever returns something went wrong - bofaRes.[Friend]_line = pLine; toReturn.Type = .Bofa; - toReturn.Data.Bofa = bofaRes; return toReturn; } diff --git a/src/Parser/BofaParserInsert.bf b/src/Parser/BofaParserInsert.bf index ffa18a2..30dafea 100644 --- a/src/Parser/BofaParserInsert.bf +++ b/src/Parser/BofaParserInsert.bf @@ -22,7 +22,6 @@ extension Bofa if(pToAdd.Type == .Text && target.Type == .Text) { target.Value.Text.Append(scope $"\n{pToAdd.Data.Text}"); - //delete pToAdd.Data.Text; return .Ok; } else if(target.Type == .Object) @@ -41,7 +40,7 @@ extension Bofa return .Ok; } return .Err; - + /* //See if we can insert and do so if(pToAdd.Depth == 0 || (pToAdd.Type == .Text && pToAdd.Depth == 1)) diff --git a/src/Parser/ParserEntryUnion.bf b/src/Parser/ParserEntryUnion.bf index 531f037..e9e3b4b 100644 --- a/src/Parser/ParserEntryUnion.bf +++ b/src/Parser/ParserEntryUnion.bf @@ -5,6 +5,6 @@ using System; [Union] struct ParserEntryUnion { - public Bofa Bofa; + public Bofa Bofa = null; public StringView Text; } \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf index 33ef40b..8db8381 100644 --- a/src/Program.bf +++ b/src/Program.bf @@ -8,13 +8,14 @@ class Program public static void Main() { - - Bofa.Testing.Profiling.Profiling_Depth_Testing(); - Bofa.Testing.Profiling.Profiling_Depth_Testing_Medium(); - Bofa.Testing.Profiling.Profiling_Normal(); - Bofa.Testing.Profiling.Profiling_Normal_Medium(); - Bofa.Testing.Profiling.Profiling_Normal_Large(); - Bofa.Testing.Profiling.Profiling_Texts(); - Bofa.Testing.Profiling.Profiling_Texts_Large(); + Bofa.Testing.Profiling.Profiling_Depth_Testing(); + Bofa.Testing.Profiling.Profiling_Depth_Testing_Medium(); + Bofa.Testing.Profiling.Profiling_Normal(); + Bofa.Testing.Profiling.Profiling_Normal_Medium(); + Bofa.Testing.Profiling.Profiling_Normal_Large(); + Bofa.Testing.Profiling.Profiling_Texts(); + Bofa.Testing.Profiling.Profiling_Texts_Large(); + + Console.Read(); } } \ No newline at end of file diff --git a/src/Testing/Profiling.bf b/src/Testing/Profiling.bf index f7ebcd0..bbd7a6c 100644 --- a/src/Testing/Profiling.bf +++ b/src/Testing/Profiling.bf @@ -12,6 +12,7 @@ class Profiling { for (int i < 1000) { + String toParse = scope .(); toParse.Append(scope $""" l one line of text @@ -20,7 +21,7 @@ class Profiling t text goes here - Text addendum n tone 12.5 - #husdhfiudshfds + husdhfiudshfds bn biggie 65645645645.6 i int 234345 bi bint 38432847329847329 From d65818c54cd3f33dabfeeb9fd08c38796d78ceec Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 26 Aug 2024 12:35:29 +0200 Subject: [PATCH 19/22] finished serialization --- BeefProj.toml | 1 + src/Bofa.bf | 10 +- src/BofaParser.bf | 27 +- src/BofaValue.bf | 2 + src/Extension.bf | 482 +++++++++++++++++++++++++++++++++++ src/Program.bf | 21 -- src/Testing/Consistency.bf | 45 ---- src/Testing/Fuzzing.bf | 4 +- src/Testing/Serialization.bf | 8 +- src/eBofaType.bf | 2 + 10 files changed, 525 insertions(+), 77 deletions(-) delete mode 100644 src/Program.bf delete mode 100644 src/Testing/Consistency.bf diff --git a/BeefProj.toml b/BeefProj.toml index ddfd45a..0d15fdc 100644 --- a/BeefProj.toml +++ b/BeefProj.toml @@ -2,4 +2,5 @@ FileVersion = 1 [Project] Name = "Bofa" +TargetType = "BeefLib" StartupObject = "Bofa.Program" diff --git a/src/Bofa.bf b/src/Bofa.bf index 779fd58..1dc3fb3 100644 --- a/src/Bofa.bf +++ b/src/Bofa.bf @@ -6,7 +6,7 @@ using System.Collections; class Bofa { - private String _line = null ~ if(_ != null) delete _; //The actual line + private String _line = null ~ delete _; //The actual line private Bofa _lastObject = null; //If we are a container we keep track of the last container inside of us public StringView Name; @@ -29,13 +29,13 @@ class Bofa if(target.Type == .Array) { depth++; - for(var i in Value.Array.Reversed) + for(var i in target.Value.Array.Reversed) toProcess.Add((depth, i)); } else if(target.Type == .Object) { depth++; - for(var i in Value.Object) + for(var i in target.Value.Object) toProcess.Add((depth, i.value)); } @@ -60,6 +60,8 @@ class Bofa strBuffer.Append(scope $"a {Name}"); case .BigInteger: strBuffer.Append(scope $"bi {Name} {Value.BigInteger}"); + case .BigUnsignedInteger: + strBuffer.Append(scope $"bui {Name} {Value.BigUnsignedInteger}"); case .BigNumber: strBuffer.Append(scope $"bn {Name} {Value.BigNumber:R}"); case .Boolean: @@ -68,6 +70,8 @@ class Bofa strBuffer.Append(scope $"c {Typename} {Name} {Value.Custom}"); case .Integer: strBuffer.Append(scope $"i {Name} {Value.Integer}"); + case .UnsignedInteger: + strBuffer.Append(scope $"ui {Name} {Value.UnsignedInteger}"); case .Line: strBuffer.Append(scope $"l {Name} {Value.Line}"); case .Number: diff --git a/src/BofaParser.bf b/src/BofaParser.bf index ab8272c..64c3f7e 100644 --- a/src/BofaParser.bf +++ b/src/BofaParser.bf @@ -50,7 +50,7 @@ class BofaParser } if (entry.Type == .Error) { - if(entry.Data.Bofa != null) + if (entry.Data.Bofa != null) delete entry.Data.Bofa; pErrors.Add(line); continue; @@ -168,6 +168,10 @@ class BofaParser typeName = "Integer"; case "bi": typeName = "BigInteger"; + case "ui": + typeName = "UnsignedInteger"; + case "bui": + typeName = "BigUnsignedInteger"; case "t": typeName = "Text"; case "a": @@ -208,7 +212,7 @@ class BofaParser bofaRes.Type = .Array; bofaRes.Value.Array = new .(); } - + return toReturn; } #endregion @@ -278,7 +282,24 @@ class BofaParser toReturn.Type = .Error; return toReturn; } - bofaRes.Value.BigInteger = result.Value; + case "ui": + bofaRes.Type = .UnsignedInteger; + var result = uint32.Parse(line); + if (result case .Err) + { + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.UnsignedInteger = result.Value; + case "bui": + bofaRes.Type = .BigUnsignedInteger; + var result = uint64.Parse(line); + if (result case .Err) + { + toReturn.Type = .Error; + return toReturn; + } + bofaRes.Value.BigUnsignedInteger = result.Value; case "t": bofaRes.Value.Text = new String(line); bofaRes.Type = .Text; diff --git a/src/BofaValue.bf b/src/BofaValue.bf index ad60bd0..2399e0e 100644 --- a/src/BofaValue.bf +++ b/src/BofaValue.bf @@ -12,6 +12,8 @@ struct BofaValue public double BigNumber; public int32 Integer; public int64 BigInteger; + public uint32 UnsignedInteger; + public uint64 BigUnsignedInteger; public bool Boolean; public StringView Custom; public Dictionary Object; diff --git a/src/Extension.bf b/src/Extension.bf index bacdd8c..606e67d 100644 --- a/src/Extension.bf +++ b/src/Extension.bf @@ -1,4 +1,8 @@ using Bofa.Serialization; +using Bofa; +using System; +using System.Collections; + namespace System { @@ -11,6 +15,63 @@ namespace System } extension Int : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Integer; + pTarget.Typename = "Integer"; + pTarget.Value.Integer = (.)Math.Clamp(this, int32.MinValue, int32.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .Integer) + return false; + this = Math.Clamp(pInput.Value.Integer, int.MaxValue, int.MinValue); + return true; + } + } + + extension Int8 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Integer; + pTarget.Typename = "Integer"; + pTarget.Value.Integer = (.)Math.Clamp(this, int8.MinValue, int8.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .Integer) + return false; + this = (.)Math.Clamp(pInput.Value.Integer, int8.MaxValue, int8.MinValue); + return true; + } + } + + extension Int16 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Integer; + pTarget.Typename = "Integer"; + pTarget.Value.Integer = (.)Math.Clamp(this, int16.MinValue, int16.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .Integer) + return false; + this = (.)Math.Clamp(pInput.Value.Integer, int16.MaxValue, int16.MinValue); + return true; + } + } + + extension Int32 : IBofaParseable { public bool Serialize(Bofa.Bofa pTarget) { @@ -28,4 +89,425 @@ namespace System return true; } } + + extension Int64 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .BigInteger; + pTarget.Typename = "BigInteger"; + pTarget.Value.BigInteger = (.)this; + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .BigInteger) + return false; + this = (.)pInput.Value.BigInteger; + return true; + } + } + + extension UInt : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .UnsignedInteger; + pTarget.Typename = "UnsignedInteger"; + pTarget.Value.UnsignedInteger = (.)Math.Clamp(this, uint32.MinValue, uint32.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .UnsignedInteger) + return false; + this = (.)Math.Clamp(pInput.Value.UnsignedInteger, uint.MaxValue, uint.MinValue); + return true; + } + } + + extension UInt8 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .UnsignedInteger; + pTarget.Typename = "UnsignedInteger"; + pTarget.Value.UnsignedInteger = (.)Math.Clamp(this, uint8.MinValue, uint8.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .UnsignedInteger) + return false; + this = (.)Math.Clamp(pInput.Value.UnsignedInteger, uint8.MaxValue, uint8.MinValue); + return true; + } + } + + extension UInt16 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .UnsignedInteger; + pTarget.Typename = "UnsignedInteger"; + pTarget.Value.UnsignedInteger = (.)Math.Clamp(this, uint16.MinValue, uint16.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .UnsignedInteger) + return false; + this = (.)Math.Clamp(pInput.Value.UnsignedInteger, uint16.MaxValue, uint16.MinValue); + return true; + } + } + + extension UInt32 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .UnsignedInteger; + pTarget.Typename = "UnsignedInteger"; + pTarget.Value.UnsignedInteger = (.)Math.Clamp(this, uint32.MinValue, uint32.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .UnsignedInteger) + return false; + this = (.)Math.Clamp(pInput.Value.UnsignedInteger, uint32.MaxValue, uint32.MinValue); + return true; + } + } + + extension UInt64 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .BigUnsignedInteger; + pTarget.Typename = "BigUnsignedInteger"; + pTarget.Value.BigUnsignedInteger = (.)Math.Clamp(this, uint64.MinValue, uint64.MaxValue); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .BigUnsignedInteger) + return false; + this = (.)Math.Clamp(pInput.Value.BigUnsignedInteger, uint64.MaxValue, uint64.MinValue); + return true; + } + } + + extension Char8 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Text; + pTarget.Typename = "Text"; + pTarget.Value.Text = new String()..Append(this); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type == .Text) + this = pInput.Value.Text[0]; + else if(pInput.Type == .Line) + this = pInput.Value.Line[0]; + else + return false; + return true; + } + } + + extension Char16 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Text; + pTarget.Typename = "Text"; + pTarget.Value.Text = new String()..Append(this); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type == .Text) + this = pInput.Value.Text[0]; + else if(pInput.Type == .Line) + this = pInput.Value.Line[0]; + else + return false; + return true; + } + } + + extension Char32 : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Text; + pTarget.Typename = "Text"; + pTarget.Value.Text = new String()..Append(this); + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type == .Text) + this = pInput.Value.Text[0]; + else if(pInput.Type == .Line) + this = pInput.Value.Line[0]; + else + return false; + return true; + } + } + + extension Float : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Number; + pTarget.Typename = "Number"; + pTarget.Value.Number = (.)this; + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .Number) + return false; + this = (.)pInput.Value.Number; + return true; + } + } + + extension Double : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .BigNumber; + pTarget.Typename = "BigNumber"; + pTarget.Value.BigNumber = (.)this; + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) mut + { + if(pInput.Type != .BigNumber) + return false; + this = (.)pInput.Value.BigNumber; + return true; + } + } + + extension String : IBofaParseable + { + public bool Serialize(Bofa.Bofa pTarget) + { + if(this.Contains('\n')) + { + pTarget.Type = .Text; + pTarget.Typename = "Text"; + pTarget.Value.Text = new .(this); + } + else + { + pTarget.Type = .Line; + pTarget.Typename = "Line"; + pTarget.Value.Line = this; + } + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) + { + this.Clear(); + if(pInput.Type == .Line) + this.Append(pInput.Value.Line); + else if(pInput.Type == .Text) + this.Append(pInput.Value.Text); + else + return false; + return true; + } + + } +} + +namespace System.Collections +{ + extension List : IBofaParseable where T : IBofaParseable where T : new where T : delete where T : class + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Array; + pTarget.Typename = "Array"; + pTarget.Value.Array = new .(this.Count); + for(var i in this) + { + Bofa toAdd = new .(); + toAdd.[Friend]_line = new .(@i.Index); + toAdd.Name = toAdd.[Friend]_line; + if(!i.Serialize(toAdd)) + { + delete toAdd; + continue; + } + else + { + pTarget.Value.Array.Add(toAdd); + continue; + } + } + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) + { + if(pInput.Type != .Array) + return false; + for(var i in pInput.Value.Array) + { + var toParse = new T(); + if(!toParse.Deserialize(i)) + delete toParse; + else + this.Add((.)toParse); + + } + return true; + } + } + + extension List : IBofaParseable where T : IBofaParseable where T : struct where T : new + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Array; + pTarget.Typename = "Array"; + pTarget.Value.Array = new .(this.Count); + for(var i in this) + { + Bofa toAdd = new .(); + toAdd.[Friend]_line = new .(@i.Index); + toAdd.Name = toAdd.[Friend]_line; + if(!i.Serialize(toAdd)) + { + delete toAdd; + continue; + } + else + { + pTarget.Value.Array.Add(toAdd); + continue; + } + } + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) + { + if(pInput.Type != .Array) + return false; + for(var i in pInput.Value.Array) + { + var toParse = T(); + if(toParse.Deserialize(i)) + this.Add((.)toParse); + + } + return true; + } + } + + extension Dictionary : IBofaParseable where TKey : String where TValue : IBofaParseable where TValue : new where TValue : delete where TValue : class + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Object; + pTarget.Typename = "Object"; + pTarget.Value.Object = new .(); + for(var i in this) + { + Bofa toAdd = new .(); + toAdd.[Friend]_line = new .(@i.Key); + toAdd.Name = toAdd.[Friend]_line; + if(!i.value.Serialize(toAdd)) + { + delete toAdd; + continue; + } + else + { + pTarget.Value.Array.Add(toAdd); + continue; + } + } + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) + { + if(pInput.Type != .Object) + return false; + for(var i in pInput.Value.Object) + { + var toParse = new TValue(); + if(toParse.Deserialize(i.value)) + this.Add(new .(i.key), toParse); + else + delete toParse; + + } + return true; + } + } + + extension Dictionary : IBofaParseable where TKey : String where TValue : IBofaParseable where TValue : new where TValue : struct + { + public bool Serialize(Bofa.Bofa pTarget) + { + pTarget.Type = .Object; + pTarget.Typename = "Object"; + pTarget.Value.Object = new .(); + for(var i in this) + { + Bofa toAdd = new .(); + toAdd.[Friend]_line = new .(@i.Key); + toAdd.Name = toAdd.[Friend]_line; + if(!i.value.Serialize(toAdd)) + { + delete toAdd; + continue; + } + else + { + pTarget.Value.Array.Add(toAdd); + continue; + } + } + return true; + } + + public bool Deserialize(Bofa.Bofa pInput) + { + if(pInput.Type != .Object) + return false; + for(var i in pInput.Value.Object) + { + var toParse = TValue(); + if(toParse.Deserialize(i.value)) + this.Add(new .(i.key), toParse); + } + return true; + } + } } \ No newline at end of file diff --git a/src/Program.bf b/src/Program.bf deleted file mode 100644 index 8db8381..0000000 --- a/src/Program.bf +++ /dev/null @@ -1,21 +0,0 @@ -namespace Bofa; - -using System; -using System.Collections; - -class Program -{ - - public static void Main() - { - Bofa.Testing.Profiling.Profiling_Depth_Testing(); - Bofa.Testing.Profiling.Profiling_Depth_Testing_Medium(); - Bofa.Testing.Profiling.Profiling_Normal(); - Bofa.Testing.Profiling.Profiling_Normal_Medium(); - Bofa.Testing.Profiling.Profiling_Normal_Large(); - Bofa.Testing.Profiling.Profiling_Texts(); - Bofa.Testing.Profiling.Profiling_Texts_Large(); - - Console.Read(); - } -} \ No newline at end of file diff --git a/src/Testing/Consistency.bf b/src/Testing/Consistency.bf deleted file mode 100644 index 6541d4d..0000000 --- a/src/Testing/Consistency.bf +++ /dev/null @@ -1,45 +0,0 @@ -namespace Bofa.Testing; - -using Bofa; - -using System; -using System.Collections; - -class Consistency -{ - [Test(Name="Reverse simple")] - public static void Standart() - { - String content = """ - l one line of text - b bool true - t textgoes here - - Text addendum - n tone 12.5 - bn biggie 65645654535.553001 - i int 234345 - bi bint 38432847329847329 - o object - b content true - a array - b content true - b content true - """; - Dictionary output = new .(); - List errors = new .(); - BofaParser.Parse(content, output, errors); - - String s = scope .(); - for(var i in output) - { - i.value.ToString(s); - s.Append('\n'); - } - s.RemoveFromEnd(1); - - Test.Assert(content == s); - - DeleteDictionaryAndValues!(output); - delete errors; - } -} \ No newline at end of file diff --git a/src/Testing/Fuzzing.bf b/src/Testing/Fuzzing.bf index 08ddd0a..4374964 100644 --- a/src/Testing/Fuzzing.bf +++ b/src/Testing/Fuzzing.bf @@ -7,7 +7,7 @@ using System.Collections; class Fuzzing { - //[Test(Name = "Fuzzing - 10 * 1000000 random characters")] + [Test(Name = "Fuzzing - 10 * 1000000 random characters")] public static void Fuzzin_Random() { for (int i < 10) @@ -25,7 +25,7 @@ class Fuzzing } } - //[Test(Name = "Fuzzing - 10 * 10000000 random characters")] + [Test(Name = "Fuzzing - 10 * 10000000 random characters")] public static void Fuzzin_Random_Large() { for (int i < 10) diff --git a/src/Testing/Serialization.bf b/src/Testing/Serialization.bf index 6baaa0a..6c21d96 100644 --- a/src/Testing/Serialization.bf +++ b/src/Testing/Serialization.bf @@ -1,6 +1,7 @@ namespace Bofa.Testing; using System; +using System.Collections; using Bofa; using Bofa.Serialization; @@ -8,18 +9,19 @@ using Bofa.Serialization; [BofaSerialize] class Serialization { - public int anInteger = (.)1; + public int anInteger = 1; + public String aString = "Value"; + public List listOfStrings = new .() ~ DeleteContainerAndItems!(_); [Test] public static void Test() { Serialization s = scope .(); + s.listOfStrings.Add(new .("dfdsfdsfdsf")); Bofa b = scope .(); b.Name = "s"; s.Serialize(b); - Console.WriteLine(b.ToString(.. scope .())); - //Console.Read(); } } \ No newline at end of file diff --git a/src/eBofaType.bf b/src/eBofaType.bf index d3e253c..d3dab82 100644 --- a/src/eBofaType.bf +++ b/src/eBofaType.bf @@ -8,6 +8,8 @@ enum EBofaType BigNumber, //64bit floating point number Integer, //32bit signed integer BigInteger, //64bit signed integer + UnsignedInteger, //32bit unsigned integer + BigUnsignedInteger, //64bit unsigned integer Boolean, //8bit true or false Object, // Key-Value container Array, //Numeric container From 8d042baf8522a772399d0b1f6eed63468c74f3a8 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 26 Aug 2024 13:28:04 +0200 Subject: [PATCH 20/22] Update README.md --- README.md | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3979052..f2b4247 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,140 @@ -# Bofa -Books object format a +# Bofa - Books Object Format A +Bofa is an object notation for general purpose use in serialization and deserialization. +The primary focus is on being human readable, while also being extremely easy to parse +This repository implements a Bofa parser in the Beef programming language. + +``` +# A floating point number +n number 125.435 +l line this is a normal line +a Array + t text you can + - put more text in here + t text2 and even + - more in here +``` + +## Index +- How to install +- The Bofa notation +- Parser notes +- Bofa parser API usage +- Potential improvements + +## How to install +- Download the repository, either with git, the download zip functionality or the release tab +- Create or open your existing Beef project +- Right click on the workspace panel +- Select "Add Existing Project" +- Navigate to the BeefProj.toml file inside the Bofa folder +- Right click on the project you want to use Bofa with +- Click "Properties" -> "Dependencies" +- Check the box that says Bofa +- Add the Bofa namespace to the files you want to use Bofa with +- Use Bofa + +## The Bofa notation +The notation itself is pretty simple. +Every line contains one Bofa "Entry", but empty lines and comments are also allowed. +A normal Bofa entry has 3 Parts: `{Type} {Name} {Value}` + +The possible values of `{Type}` are: +- l - Line - A string (utf8) without a newline character +- t - Text - A string (utf8) that may contain newline characters +- b - Boolean - A boolean value of either "true" or "false" +- i - Integer - A 32bit signed integer +- ui - UnsignedInteger - A 32bit unsigned integer +- bi - BigInteger - A 64bit signed integer +- bui - BigUnsignedInteger - A 64bit unsigned integer +- n - Number - A 32bit floating point number +- bn - BigNumber - A 64bit floating point number +- c - Custom - Any custom type in a string (utf8) representation +- o - Object - A Key/Value container for other Bofa entries +- a - Array - A container for other Bofa entries, where entries may have identical names + +`{Name}` is simple just a string that does not contain a space or tab character +`{Value}` is a string that represents the choosen datatype and can be parsed into the datatype + +Empty lines are full ignored and comments start with a # as the first non whitespace character in the line. + +An entry of type custom needs additional information to work. +Instead of `{Type} {Name} {Value}` a custom entry uses `{Type} {Typename} {Name} {Value}` instead. +Similarly arrays and objects dont actually need a entry for `{Value}` and just use `{Type} {Name}`. +In order to allow multiline text without too many issues the `-` character is used to indicate that the content of this line should be appended +to the last line if it was of type text. + +Membership of containers like arrays or objects is indicated via a depth value. +In order to indicate depth the start of the line may contain any number of tabs or spaces, the total amount of which indicates the depth of the entry. +The exact object it is a member of is always the last defined object at a given depth. +``` +a Array1 + a Array2 + a Array3 + l Line this line is a member of Array3 which is itself contained inside of Array1 +``` +Objects have a key uniqueness rules, while Arrays dont have this (Entries of an array still need to have a proper name though, even if its only "-"). + +## Parser notes +Bofa should always be parsed loosely and to the best of the parsers ability, but never fail completely. +Instead it can indicate on which line an error occured and leave the user to figure out wether to stop or to continue. +This also enables a parsing pattern where Bofa data can be structured so any parser can read a document from a newer or different parser: +``` +# The following line has a type that was added by a imaginary parser using the Bofa 2.0 Standard +rgb color 255:0:255 +c rgb color 255:0:255 +``` +A parser that supports 2.0 should just parse the first entry and ignore the second, as it contains a dublicate name. +A parser still on an old version will ignore the first one, since it doesnt know a type named rgb but instead parse the second one correctly + +While the insertion at a depth needs to be done in the order of the document, the parsing and validation of the individual line does not. +As such you can theoretically multithread the parsing of each individual line to get some potential speed. + +Different parsers may add different types for their usecases, but single and 2 character typenames should stay reserved for official notation types. + +The entire standard is case sensitive. + +## Bofa parser api usage +This shows of an example of how to use the parser api +```cs +namespace Example; + +using System; +using Bofa; + +class ExampleClass +{ + public static void Main() + { + String bofaString = """ + # A floating point number + n number 125.435 + l line this is a normal line + a Array + t text you can + - put more text in here + t text2 and even + - more in here + """; + + Dictionary output = new .(); + List errors = new .(); + BofaParser.Parse(bofaString, output, errors); + + DeleteDictionaryAndValues!(output); + delete errors; + } +} +``` + +## Potential improvements +- There is still alot of speed left on the table + - Reduce the amount of allocations + - Multithread initial parsing +- New useful types + - Color + - Version + - Encrypted raw data +- More automatic serialization/deserialization in Corlib + - Hashes + - Pointers + - Tuples \ No newline at end of file From 08c518d5dc658629ecdcf7a99102aca4c3a425b4 Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 26 Aug 2024 13:29:32 +0200 Subject: [PATCH 21/22] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f2b4247..58d3817 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Bofa - Books Object Format A +# Bofa - Books Object Format A - 1.0.0 Bofa is an object notation for general purpose use in serialization and deserialization. The primary focus is on being human readable, while also being extremely easy to parse This repository implements a Bofa parser in the Beef programming language. @@ -16,6 +16,7 @@ a Array ## Index - How to install +- Changelog - The Bofa notation - Parser notes - Bofa parser API usage @@ -33,6 +34,12 @@ a Array - Add the Bofa namespace to the files you want to use Bofa with - Use Bofa +## Changelog +- Version 1.0.0 + - Initial Version + - Fast parsing + - Add automated serialization generation + ## The Bofa notation The notation itself is pretty simple. Every line contains one Bofa "Entry", but empty lines and comments are also allowed. From 9eb85812b3d42eabb6b8b2e3ee4b5eea8f52a20e Mon Sep 17 00:00:00 2001 From: Booklordofthedings Date: Mon, 26 Aug 2024 13:31:44 +0200 Subject: [PATCH 22/22] added copyright stuff --- BeefProj.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BeefProj.toml b/BeefProj.toml index 0d15fdc..87a15ea 100644 --- a/BeefProj.toml +++ b/BeefProj.toml @@ -4,3 +4,11 @@ FileVersion = 1 Name = "Bofa" TargetType = "BeefLib" StartupObject = "Bofa.Program" + +[Platform.Windows] +Description = "A parser for Books Object Format A" +Company = "Booklordofthedings" +Product = "Bofa" +Copyright = "Booklordofthedings" +FileVersion = "1.0.0" +ProductVersion = "1.0.0"