Update to version 1.0.0 #3

Merged
Booklordofthedings merged 23 commits from dev into main 2024-08-26 13:33:38 +02:00
10 changed files with 375 additions and 110 deletions
Showing only changes of commit 501a4af636 - Show all commits

View file

@ -2,5 +2,4 @@ FileVersion = 1
[Project]
Name = "Bofa"
TargetType = "BeefLib"
StartupObject = "Bofa.Program"

View file

@ -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<Bofa> 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<Bofa> Get(int pIndex)
{
if(Type != .Array)
return .Err;
if(!(Value.Array.Count > pIndex))
return .Err;
return Value.Array[pIndex];
}
}

View file

@ -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

View file

@ -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;
}
}
}

20
src/Program.bf Normal file
View file

@ -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();
}
}

View file

@ -0,0 +1,13 @@
namespace Bofa.Serialization;
using System;
struct BofaIncludeAttribute : Attribute
{
public StringView Name;
public this(StringView pName)
{
Name = pName;
}
}

View file

@ -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<BofaIncludeAttribute>())
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<BofaIncludeAttribute>() && f.GetCustomAttribute<BofaIncludeAttribute>() 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));
}
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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();
}
}