mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-14 14:24:10 +02:00
203 lines
3.8 KiB
Beef
203 lines
3.8 KiB
Beef
using System.Collections;
|
|
using System;
|
|
using Beefy;
|
|
using System.IO;
|
|
using System.Diagnostics;
|
|
using System.Threading;
|
|
|
|
namespace IDE
|
|
{
|
|
class CompositeFile
|
|
{
|
|
public static String sMainFileName = "@main.bf";
|
|
|
|
public Monitor mMonitor = new .() ~ delete _;
|
|
static String sVersionStr = "///@singleFileVersion ";
|
|
static String sSectionStr = "///@embed ";
|
|
public Dictionary<String, String> mData = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
|
|
public String mFilePath ~ delete _;
|
|
public bool mPendingSave;
|
|
public bool mHasChanges;
|
|
|
|
public this(StringView filePath)
|
|
{
|
|
Debug.Assert(mFilePath == null);
|
|
mFilePath = new String(filePath);
|
|
}
|
|
|
|
public ~this()
|
|
{
|
|
if (mHasChanges)
|
|
Save();
|
|
}
|
|
|
|
public bool HasUnsavedChanges
|
|
{
|
|
get
|
|
{
|
|
return mHasChanges;
|
|
}
|
|
}
|
|
|
|
public bool HasPendingSave
|
|
{
|
|
get
|
|
{
|
|
return mPendingSave;
|
|
}
|
|
}
|
|
|
|
public StringView FilePath
|
|
{
|
|
get
|
|
{
|
|
return mFilePath;
|
|
}
|
|
}
|
|
|
|
public bool IsIncluded(StringView name)
|
|
{
|
|
return name == sMainFileName;
|
|
}
|
|
|
|
public Result<void> Load()
|
|
{
|
|
String source = scope String();
|
|
if (File.ReadAllText(mFilePath, source, false) case .Err)
|
|
return .Err;
|
|
|
|
bool isMain = true;
|
|
String embedName = scope .(sMainFileName);
|
|
String content = scope .();
|
|
|
|
for (let line in source.Split('\n'))
|
|
{
|
|
if (line.StartsWith(sSectionStr))
|
|
{
|
|
Set(embedName, content);
|
|
embedName.Clear();
|
|
content.Clear();
|
|
embedName.Append(line, sSectionStr.Length);
|
|
isMain = false;
|
|
|
|
}
|
|
else if (line.StartsWith(sVersionStr))
|
|
{
|
|
// Ignore
|
|
int version = int.Parse(StringView(line, sVersionStr.Length)).GetValueOrDefault();
|
|
if (version != 1)
|
|
{
|
|
gApp.OutputLineSmart("ERROR: File '{0}' specifies invalid file version '{1}'. Beef upgrade required?", mFilePath, version);
|
|
return .Err;
|
|
}
|
|
}
|
|
else if (isMain)
|
|
{
|
|
if (!content.IsEmpty)
|
|
content.Append("\n");
|
|
content.Append(line);
|
|
}
|
|
else if (line.StartsWith("/// "))
|
|
{
|
|
if (!content.IsEmpty)
|
|
content.Append("\n");
|
|
content.Append(line, 4);
|
|
}
|
|
}
|
|
Set(embedName, content);
|
|
mHasChanges = false;
|
|
mPendingSave = false;
|
|
return .Ok;
|
|
}
|
|
|
|
public bool Get(StringView name, String outData)
|
|
{
|
|
using (mMonitor.Enter())
|
|
{
|
|
if (mData.TryGetValue(scope String()..Append(name), var value))
|
|
{
|
|
outData.Append(value);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void Set(StringView name, StringView data)
|
|
{
|
|
using (mMonitor.Enter())
|
|
{
|
|
bool added = mData.TryAdd(scope String()..Append(name), var keyPtr, var valuePtr);
|
|
if (added)
|
|
{
|
|
mHasChanges = true;
|
|
mPendingSave = true;
|
|
*keyPtr = new String(name);
|
|
*valuePtr = new String(data);
|
|
}
|
|
else
|
|
{
|
|
if (*valuePtr != data)
|
|
{
|
|
mHasChanges = true;
|
|
mPendingSave = true;
|
|
(*valuePtr).Set(data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool Save()
|
|
{
|
|
using (mMonitor.Enter())
|
|
{
|
|
mPendingSave = false;
|
|
if (!mHasChanges)
|
|
return true;
|
|
|
|
String str = scope String();
|
|
|
|
void Add(StringView name)
|
|
{
|
|
String sectionStr = scope String();
|
|
Get(name, sectionStr);
|
|
if (name == sMainFileName)
|
|
{
|
|
for (let line in sectionStr.Split('\n'))
|
|
{
|
|
if (@line.Pos != 0)
|
|
str.Append("\n");
|
|
str.Append(line);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!sectionStr.IsEmpty)
|
|
{
|
|
str.Append("\n");
|
|
str.Append(sSectionStr);
|
|
str.Append(name);
|
|
str.Append("\n");
|
|
|
|
for (let line in sectionStr.Split('\n'))
|
|
{
|
|
str.Append("/// ");
|
|
str.Append(line);
|
|
str.Append("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
Add(sMainFileName);
|
|
str.Append("\n", sVersionStr, "1\n");
|
|
Add("Workspace");
|
|
Add("Project");
|
|
|
|
if (!gApp.SafeWriteTextFile(mFilePath, str))
|
|
return false;
|
|
mHasChanges = true;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|