mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
First Commit
This commit is contained in:
407
CrossLangFile.cs
Normal file
407
CrossLangFile.cs
Normal file
@@ -0,0 +1,407 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace CrossLangDevStudio;
|
||||
|
||||
|
||||
public class CrossLangFile
|
||||
{
|
||||
const string CROSSVM = "TCROSSVM";
|
||||
public void Load(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
using (var strm = File.OpenRead(path))
|
||||
Load(strm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Load(Stream strm)
|
||||
{
|
||||
byte[] header = new byte[18];
|
||||
strm.ReadExactly(header);
|
||||
for (int i = 0; i < CROSSVM.Length; i++)
|
||||
{
|
||||
if (header[i] != (byte)CROSSVM[i]) throw new Exception("Invalid signature");
|
||||
}
|
||||
|
||||
Version = new CrossLangVersion(header, 13);
|
||||
|
||||
uint ReadInt()
|
||||
{
|
||||
strm.ReadExactly(header, 0, 4);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(header, 0, 4);
|
||||
return BitConverter.ToUInt32(header, 0);
|
||||
}
|
||||
|
||||
void ReadString()
|
||||
{
|
||||
uint length = ReadInt();
|
||||
byte[] data = new byte[length];
|
||||
strm.ReadExactly(data, 0, data.Length);
|
||||
Strings.Add(Encoding.UTF8.GetString(data));
|
||||
}
|
||||
string ReadSectionName()
|
||||
{
|
||||
strm.ReadExactly(header, 0, 4);
|
||||
return Encoding.UTF8.GetString(header, 0, 4);
|
||||
}
|
||||
|
||||
string GetString()
|
||||
{
|
||||
uint index = ReadInt();
|
||||
return Strings[(int)index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint count = ReadInt();
|
||||
for (uint i = 0; i < count; i++)
|
||||
{
|
||||
string section = ReadSectionName();
|
||||
uint sectionSize = ReadInt();
|
||||
switch (section)
|
||||
{
|
||||
case "STRS":
|
||||
{
|
||||
uint theCount = ReadInt();
|
||||
for (uint j = 0; j < theCount; j++)
|
||||
{
|
||||
ReadString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "NAME":
|
||||
Name = GetString();
|
||||
break;
|
||||
case "INFO":
|
||||
Info = GetString();
|
||||
break;
|
||||
case "ICON":
|
||||
Icon = (int)ReadInt();
|
||||
break;
|
||||
case "RESO":
|
||||
byte[] data = new byte[sectionSize];
|
||||
strm.ReadExactly(data, 0, data.Length);
|
||||
Resources.Add(data);
|
||||
break;
|
||||
case "DEPS":
|
||||
if (sectionSize == 9)
|
||||
{
|
||||
string name = GetString();
|
||||
strm.ReadExactly(header, 0, 5);
|
||||
var version = new CrossLangVersion(header);
|
||||
Dependencies.Add(new CrossLangDependency() { Name = name, Version = version });
|
||||
}
|
||||
break;
|
||||
default:
|
||||
strm.Position += sectionSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public string Name { get; private set; } = "";
|
||||
public CrossLangVersion Version { get; private set; }
|
||||
|
||||
public string Info { get; private set; } = "";
|
||||
|
||||
public int Icon { get; private set; } = -1;
|
||||
|
||||
public CrossLangInfo InfoObject => JsonConvert.DeserializeObject<CrossLangInfo>(Info) ?? new CrossLangInfo();
|
||||
|
||||
public Bitmap GetIcon(int height=128)
|
||||
{
|
||||
using (Stream strm = (Icon > -1 && Icon < Resources.Count) ? new MemoryStream(Resources[Icon], false) : AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.ico")))
|
||||
{
|
||||
return Bitmap.DecodeToHeight(strm, height);
|
||||
}
|
||||
}
|
||||
|
||||
internal string GetTemplatePrettyName()
|
||||
{
|
||||
var info = InfoObject;
|
||||
if (info is not null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(info.TemplateNamePretty)) return info.TemplateNamePretty;
|
||||
if (!string.IsNullOrWhiteSpace(info.TemplateName)) return info.TemplateName;
|
||||
}
|
||||
return this.Name;
|
||||
}
|
||||
|
||||
public List<string> Strings { get; } = new List<string>();
|
||||
|
||||
public List<byte[]> Resources { get; } = new List<byte[]>();
|
||||
|
||||
public List<CrossLangDependency> Dependencies { get; } = new List<CrossLangDependency>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class CrossLangConfig
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonProperty("version")]
|
||||
public CrossLangVersion Version { get; set; }
|
||||
|
||||
[JsonProperty("dependencies")]
|
||||
public List<CrossLangDependency> Dependencies { get; set; } = new List<CrossLangDependency>();
|
||||
|
||||
[JsonProperty("info")]
|
||||
public CrossLangInfo Info { get; set; } = new CrossLangInfo();
|
||||
|
||||
[JsonProperty("project_dependencies")]
|
||||
public List<string> ProjectDependencies { get; set; } = new List<string>();
|
||||
|
||||
[JsonProperty("icon")]
|
||||
public string? Icon { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class CrossLangInfo
|
||||
{
|
||||
[JsonProperty("maintainer")]
|
||||
public string? Maintainer { get; set; } //Not checked when building project
|
||||
[JsonProperty("type")]
|
||||
public string? Type { get; set; } //gets checked whether it is compile_tool by build tool, possible values are in file: project_types.txt
|
||||
[JsonProperty("repo")]
|
||||
public string? Repoository { get; set; } //optional, is the place where the code is stored
|
||||
[JsonProperty("homepage")]
|
||||
public string? HomePage { get; set; } //optional, is the website for the project
|
||||
[JsonProperty("license")]
|
||||
public string? License { get; set; } //optional, but recommended to tell people what the license is
|
||||
[JsonProperty("description")]
|
||||
public string? Description { get; set; } //optional but tells people about the package
|
||||
|
||||
[JsonProperty("template_name")]
|
||||
public string? TemplateName { get; set; }
|
||||
[JsonProperty("template_name_pretty")]
|
||||
public string? TemplateNamePretty { get; set; }
|
||||
|
||||
[JsonProperty("template_project_dependencies")]
|
||||
public JToken? TemplateDependencies { get; set; }
|
||||
|
||||
[JsonProperty("template_info")]
|
||||
public JToken? TemplateInfo { get; set; }
|
||||
[JsonProperty("template_extra_text_ftles")]
|
||||
public JToken? TemplateExtraTextFiles { get; set; }
|
||||
[JsonProperty("template_ignored_files")]
|
||||
public JToken? TemplateIgnoredFiles { get; set; }
|
||||
}
|
||||
|
||||
public class CrossLangDependency
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; } = "";
|
||||
[JsonProperty("verson")]
|
||||
public CrossLangVersion Version { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public enum CrossLangVersionStage
|
||||
{
|
||||
Development = 0,
|
||||
Alpha = 1,
|
||||
Beta = 2,
|
||||
Production = 3
|
||||
}
|
||||
public class CrossLangVersionConverter : Newtonsoft.Json.JsonConverter<CrossLangVersion>
|
||||
{
|
||||
public override CrossLangVersion ReadJson(JsonReader reader, Type objectType, CrossLangVersion existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
string? s = reader.Value as string;
|
||||
if (!string.IsNullOrWhiteSpace(s))
|
||||
{
|
||||
|
||||
if (CrossLangVersion.TryParse(s, out var version)) return version;
|
||||
|
||||
}
|
||||
|
||||
if (hasExistingValue)
|
||||
return existingValue;
|
||||
return new CrossLangVersion();
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, CrossLangVersion value, JsonSerializer serializer)
|
||||
{
|
||||
writer.WriteValue(value.ToString());
|
||||
}
|
||||
}
|
||||
[Newtonsoft.Json.JsonConverter( typeof(CrossLangVersionConverter))]
|
||||
public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
||||
{
|
||||
public void CopyTo(byte[] data, int offset = 0)
|
||||
{
|
||||
if (offset + 5 > data.Length) throw new IndexOutOfRangeException("Cannot write outside of array");
|
||||
data[offset + 0] = Major;
|
||||
data[offset + 1] = Minor;
|
||||
data[offset + 2] = Patch;
|
||||
data[offset + 3] = (byte)(BuildAndStage >> 8);
|
||||
data[offset + 4] = (byte)(BuildAndStage & 0xFF);
|
||||
}
|
||||
public byte[] ToArray()
|
||||
{
|
||||
byte[] data = new byte[5];
|
||||
CopyTo(data);
|
||||
return data;
|
||||
}
|
||||
public static bool TryParse(string str, out CrossLangVersion version)
|
||||
{
|
||||
var dashPart = str.Split(new char[] { '-' }, 2, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
byte major = 1;
|
||||
byte minor = 0;
|
||||
byte patch = 0;
|
||||
ushort build = 0;
|
||||
CrossLangVersionStage stage = CrossLangVersionStage.Development;
|
||||
if (dashPart.Length >= 1)
|
||||
{
|
||||
|
||||
var dotPart = dashPart[0].Split(new char[] { '.' }, 4, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
if (dotPart.Length > 0)
|
||||
{
|
||||
if (!byte.TryParse(dotPart[0], out major))
|
||||
{
|
||||
version = new CrossLangVersion();
|
||||
return false;
|
||||
}
|
||||
if (dotPart.Length > 1 && !byte.TryParse(dotPart[1], out minor))
|
||||
{
|
||||
version = new CrossLangVersion();
|
||||
return false;
|
||||
}
|
||||
if (dotPart.Length > 2 && !byte.TryParse(dotPart[2], out patch))
|
||||
{
|
||||
version = new CrossLangVersion();
|
||||
return false;
|
||||
}
|
||||
if (dotPart.Length > 3 && !ushort.TryParse(dotPart[3], out build))
|
||||
{
|
||||
version = new CrossLangVersion();
|
||||
return false;
|
||||
}
|
||||
if (dashPart.Length == 2)
|
||||
{
|
||||
switch (dashPart[1])
|
||||
{
|
||||
case "dev":
|
||||
stage = CrossLangVersionStage.Development;
|
||||
break;
|
||||
case "alpha":
|
||||
stage = CrossLangVersionStage.Alpha;
|
||||
break;
|
||||
case "beta":
|
||||
stage = CrossLangVersionStage.Beta;
|
||||
break;
|
||||
case "prod":
|
||||
stage = CrossLangVersionStage.Production;
|
||||
break;
|
||||
default:
|
||||
version = new CrossLangVersion();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
version = new CrossLangVersion(major, minor, patch, build, stage);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
version = new CrossLangVersion();
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
}
|
||||
public CrossLangVersion()
|
||||
{
|
||||
|
||||
}
|
||||
public CrossLangVersion(byte major, byte minor, byte patch, ushort build, CrossLangVersionStage stage)
|
||||
{
|
||||
Major = major;
|
||||
Minor = minor;
|
||||
Patch = patch;
|
||||
Build = build;
|
||||
Stage = stage;
|
||||
}
|
||||
public CrossLangVersion(byte[] data, int offset = 0)
|
||||
{
|
||||
if (offset + 5 > data.Length) return;
|
||||
|
||||
Major = data[offset+0];
|
||||
Minor = data[offset+1];
|
||||
Patch = data[offset+2];
|
||||
ushort build = (ushort)(data[offset+3] << 8 | data[offset+4]);
|
||||
Build = (ushort)(build >> 2);
|
||||
Stage = (CrossLangVersionStage)(build & 3);
|
||||
}
|
||||
public byte Major { get; set; } = 1;
|
||||
public byte Minor { get; set; } = 0;
|
||||
public byte Patch { get; set; } = 0;
|
||||
|
||||
public ushort Build { get; set; } = 0;
|
||||
|
||||
public static CrossLangVersion OnePointZeroProd => new CrossLangVersion(){Major=1,Minor=0,Patch=0,Build=0,Stage= CrossLangVersionStage.Production};
|
||||
|
||||
public CrossLangVersionStage Stage { get; set; } = CrossLangVersionStage.Development;
|
||||
|
||||
public ushort BuildAndStage => (ushort)(Build << 2 | (ushort)Stage);
|
||||
|
||||
public ulong AsInteger => (ulong)((ulong)Major << 32 | (ulong)Minor << 24 | (ulong)Patch << 16 | (ulong)BuildAndStage);
|
||||
|
||||
public int CompareTo(CrossLangVersion other)
|
||||
{
|
||||
return AsInteger.CompareTo(other.AsInteger);
|
||||
}
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is CrossLangVersion oth)
|
||||
return CompareTo(oth);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string stage="dev";
|
||||
switch (Stage)
|
||||
{
|
||||
case CrossLangVersionStage.Development:
|
||||
stage = "dev";
|
||||
break;
|
||||
case CrossLangVersionStage.Alpha:
|
||||
stage = "alpha";
|
||||
break;
|
||||
case CrossLangVersionStage.Beta:
|
||||
stage = "beta";
|
||||
break;
|
||||
case CrossLangVersionStage.Production:
|
||||
stage = "prod";
|
||||
break;
|
||||
}
|
||||
return $"{Major}.{Minor}.{Patch}.{Build}-{stage}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user