mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
407 lines
12 KiB
C#
407 lines
12 KiB
C#
|
|
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}";
|
|
}
|
|
} |