import MochaBinary from mocha-legacy
This commit is contained in:
parent
6ed80b56ad
commit
2ef33f8af3
@ -41,6 +41,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{B024
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Plugins.Libraries.Yaml", "mocha-dotnet\src\plugins\Mocha.Plugins.Libraries.Yaml\Mocha.Plugins.Libraries.Yaml.csproj", "{96400F5A-98ED-48FF-8000-6135BDF10360}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mocha.Plugins.Libraries.MochaBinary", "mocha-dotnet\src\plugins\Mocha.Plugins.Libraries.MochaBinary\Mocha.Plugins.Libraries.MochaBinary.csproj", "{2519497F-DDDA-4918-9AD0-880CAA2E541F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -71,6 +73,10 @@ Global
|
||||
{96400F5A-98ED-48FF-8000-6135BDF10360}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{96400F5A-98ED-48FF-8000-6135BDF10360}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{96400F5A-98ED-48FF-8000-6135BDF10360}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2519497F-DDDA-4918-9AD0-880CAA2E541F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2519497F-DDDA-4918-9AD0-880CAA2E541F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2519497F-DDDA-4918-9AD0-880CAA2E541F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2519497F-DDDA-4918-9AD0-880CAA2E541F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -92,6 +98,7 @@ Global
|
||||
{20B7D199-322C-4942-85FE-46B90C75E92A} = {27C300F5-5172-4225-A6F7-3503B9007DD8}
|
||||
{B024FD23-7084-4DDF-A185-D58BEE7A006F} = {66EB3261-A473-41C7-8D40-E1B4DC8ED4B3}
|
||||
{96400F5A-98ED-48FF-8000-6135BDF10360} = {B024FD23-7084-4DDF-A185-D58BEE7A006F}
|
||||
{2519497F-DDDA-4918-9AD0-880CAA2E541F} = {B024FD23-7084-4DDF-A185-D58BEE7A006F}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D28A9CF8-0235-4F8F-865F-C460BDCAE16D}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public abstract class DataFormat
|
||||
{
|
||||
protected virtual void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
protected abstract void LoadInternal(ObjectModel? objectModel, Stream stream);
|
||||
protected virtual void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
public void Load(ObjectModel? objectModel, Stream stream)
|
||||
{
|
||||
Stack<ObjectModel> stack = new Stack<ObjectModel>();
|
||||
stack.Push(objectModel);
|
||||
|
||||
BeforeLoadInternal(stack);
|
||||
|
||||
objectModel = stack.Pop();
|
||||
|
||||
LoadInternal(objectModel, stream);
|
||||
|
||||
stack.Push(objectModel);
|
||||
AfterLoadInternal(stack);
|
||||
}
|
||||
|
||||
protected virtual void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
protected abstract void SaveInternal(ObjectModel? objectModel, Stream stream);
|
||||
protected virtual void AfterSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
}
|
||||
public void Save(ObjectModel? objectModel, Stream stream)
|
||||
{
|
||||
Stack<ObjectModel> stack = new Stack<ObjectModel>();
|
||||
stack.Push(objectModel);
|
||||
|
||||
BeforeSaveInternal(stack);
|
||||
|
||||
objectModel = stack.Pop();
|
||||
|
||||
SaveInternal(objectModel, stream);
|
||||
|
||||
stack.Push(objectModel);
|
||||
AfterSaveInternal(stack);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
|
||||
namespace MBS.Editor.Core.DataFormats.YAML;
|
||||
|
||||
public class YAMLDataFormat : DataFormat
|
||||
{
|
||||
protected override void LoadInternal(ObjectModel? objectModel, Stream stream)
|
||||
{
|
||||
StreamReader sr = new StreamReader(stream);
|
||||
int ic = -1;
|
||||
while ((ic = sr.Read()) != -1)
|
||||
{
|
||||
char c = (char)ic;
|
||||
if (c == '-')
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public class Document
|
||||
{
|
||||
public ObjectModel? ObjectModel { get; set; } = null;
|
||||
public DataFormat? DataFormat { get; set; } = null;
|
||||
public Stream Stream { get; set; }
|
||||
|
||||
public Document(ObjectModel objectModel, DataFormat dataFormat, Stream stream)
|
||||
{
|
||||
ObjectModel = objectModel;
|
||||
DataFormat = dataFormat;
|
||||
Stream = stream;
|
||||
}
|
||||
|
||||
public static Document Load(ObjectModel objectModel, DataFormat dataFormat, Stream stream)
|
||||
{
|
||||
Document d = new Document(objectModel, dataFormat, stream);
|
||||
d.Load();
|
||||
return d;
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
DataFormat.Load(ObjectModel, Stream);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace MBS.Editor.Core.IO;
|
||||
|
||||
public enum Endianness
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
namespace MBS.Editor.Core.IO;
|
||||
|
||||
public enum NewLineSequence
|
||||
{
|
||||
Automatic,
|
||||
SystemDefault,
|
||||
CarriageReturn,
|
||||
LineFeed,
|
||||
CarriageReturnLineFeed,
|
||||
LineFeedCarriageReturn
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,79 @@
|
||||
using System.Text;
|
||||
|
||||
namespace MBS.Editor.Core.IO;
|
||||
|
||||
public class ReaderWriterBase
|
||||
{
|
||||
private readonly Stream _st;
|
||||
/// <summary>
|
||||
/// Exposes access to the underlying stream of the <see cref="ReaderWriterBase" />.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The underlying stream associated with the <see cref="ReaderWriterBase" />.
|
||||
/// </value>
|
||||
public Stream BaseStream { get { return _st; } }
|
||||
|
||||
public Encoding DefaultEncoding { get; set; } = Encoding.UTF8;
|
||||
|
||||
public NewLineSequence NewLineSequence { get; set; } = NewLineSequence.SystemDefault;
|
||||
public Endianness Endianness { get; set; } = Endianness.LittleEndian;
|
||||
|
||||
public bool SwapEndianness()
|
||||
{
|
||||
if (Endianness == Endianness.LittleEndian)
|
||||
{
|
||||
Endianness = Endianness.BigEndian;
|
||||
return true;
|
||||
}
|
||||
else if (Endianness == Endianness.BigEndian)
|
||||
{
|
||||
Endianness = Endianness.LittleEndian;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected string GetNewLineSequence()
|
||||
{
|
||||
switch (NewLineSequence)
|
||||
{
|
||||
case NewLineSequence.SystemDefault: return System.Environment.NewLine;
|
||||
case NewLineSequence.CarriageReturnLineFeed: return "\r\n";
|
||||
case NewLineSequence.CarriageReturn: return "\r";
|
||||
case NewLineSequence.LineFeed: return "\n";
|
||||
}
|
||||
return System.Environment.NewLine;
|
||||
}
|
||||
|
||||
public ReaderWriterBase(Stream st)
|
||||
{
|
||||
_st = st;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aligns the <see cref="Writer" /> to the specified number of bytes. If the current
|
||||
/// position of the <see cref="Writer" /> is not a multiple of the specified number of bytes,
|
||||
/// the position will be increased by the amount of bytes necessary to bring it to the
|
||||
/// aligned position.
|
||||
/// </summary>
|
||||
/// <param name="alignTo">The number of bytes on which to align the <see cref="Reader"/>.</param>
|
||||
/// <param name="extraPadding">Any additional padding bytes that should be included after aligning to the specified boundary.</param>
|
||||
public void Align(int alignTo, int extraPadding = 0)
|
||||
{
|
||||
if (alignTo == 0)
|
||||
return;
|
||||
|
||||
long paddingCount = ((alignTo - (_st.Position % alignTo)) % alignTo);
|
||||
paddingCount += extraPadding;
|
||||
|
||||
if (_st.Position == _st.Length)
|
||||
{
|
||||
byte[] buffer = new byte[paddingCount];
|
||||
_st.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_st.Position += paddingCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public class InvalidDataFormatException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidDataFormatException" /> class.
|
||||
/// </summary>
|
||||
public InvalidDataFormatException() : base() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidDataFormatException" /> class
|
||||
/// with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public InvalidDataFormatException(string? message) : base(message) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidDataFormatException" /> class
|
||||
/// with a specified error message and a reference to the inner exception that is the
|
||||
/// cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">
|
||||
/// The exception that is the cause of the current exception, or a null reference
|
||||
/// (Nothing in Visual Basic) if no inner exception is specified.
|
||||
/// </param>
|
||||
public InvalidDataFormatException(string? message, Exception? innerException) : base(message, innerException) { }
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public abstract class ObjectModel
|
||||
{
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public class ObjectModelNotSupportedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ObjectModelNotSupportedException" /> class.
|
||||
/// </summary>
|
||||
public ObjectModelNotSupportedException() : base() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ObjectModelNotSupportedException" /> class
|
||||
/// with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public ObjectModelNotSupportedException(string? message) : base(message) { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ObjectModelNotSupportedException" /> class
|
||||
/// with a specified error message and a reference to the inner exception that is the
|
||||
/// cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">
|
||||
/// The exception that is the cause of the current exception, or a null reference
|
||||
/// (Nothing in Visual Basic) if no inner exception is specified.
|
||||
/// </param>
|
||||
public ObjectModelNotSupportedException(string? message, Exception? innerException) : base(message, innerException) { }
|
||||
|
||||
public Type? ExpectedObjectModelType { get; }
|
||||
public Type? ActualObjectModelType { get; }
|
||||
|
||||
public ObjectModelNotSupportedException(Type expectedObjectModelType, Type? actualObjectModelType) : this("The object model is not supported", expectedObjectModelType, actualObjectModelType) { }
|
||||
public ObjectModelNotSupportedException(string? message, Type expectedObjectModelType, Type? actualObjectModelType) : base(message)
|
||||
{
|
||||
ExpectedObjectModelType = expectedObjectModelType;
|
||||
ActualObjectModelType = actualObjectModelType;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public abstract class FileSource
|
||||
{
|
||||
public long Length { get { return GetLengthInternal(); } }
|
||||
|
||||
protected abstract long GetLengthInternal();
|
||||
protected abstract byte[] GetDataInternal(long offset, long length);
|
||||
|
||||
public byte[] GetData() { return GetData(0, GetLengthInternal()); }
|
||||
public byte[] GetData(long offset, long length)
|
||||
{
|
||||
byte[] data = GetDataInternal(offset, length);
|
||||
MemoryStream msInput = new MemoryStream(data);
|
||||
/*
|
||||
for (int i = 0; i < Transformations.Count; i++)
|
||||
{
|
||||
System.IO.MemoryStream msOutput = new System.IO.MemoryStream();
|
||||
Transformations[i].Function(this, msInput, msOutput);
|
||||
msInput = msOutput;
|
||||
}
|
||||
*/
|
||||
return msInput.ToArray();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
//
|
||||
// MemoryFileSource.cs - provides a FileSource for retrieving file data from a byte array
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2011-2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a <see cref="FileSource" /> for retrieving file data from a <see cref="MemoryAccessor" />.
|
||||
/// </summary>
|
||||
public class ByteArrayFileSource : FileSource
|
||||
{
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public ByteArrayFileSource(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
protected override byte[] GetDataInternal(long offset, long length)
|
||||
{
|
||||
long realLength = Math.Min(length, Data.Length);
|
||||
byte[] realData = Data;
|
||||
long remaining = realData.Length - offset;
|
||||
realLength = Math.Min(realLength, remaining);
|
||||
|
||||
byte[] data = new byte[realLength];
|
||||
Array.Copy(realData, offset, data, 0, realLength);
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override long GetLengthInternal()
|
||||
{
|
||||
return Data.Length;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
using MBS.Core.Collections;
|
||||
using MBS.Editor.Core.Compression;
|
||||
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
public class CompressedEmbeddedFileSource : EmbeddedFileSource
|
||||
{
|
||||
public CompressionModule? CompressionModule { get; set; } = null;
|
||||
|
||||
public long CompressedLength { get; set; }
|
||||
private long DecompressedLength { get; set; }
|
||||
protected override long ActualLength => DecompressedLength;
|
||||
|
||||
private byte[]? _decompressedData = null;
|
||||
|
||||
protected override byte[] GetDataInternal(long offset, long length)
|
||||
{
|
||||
if (_decompressedData == null)
|
||||
{
|
||||
Stream.Seek(Offset + offset, SeekOrigin.Begin);
|
||||
|
||||
byte[] compressedData = new byte[CompressedLength];
|
||||
Stream.Read(compressedData, 0, compressedData.Length);
|
||||
Console.WriteLine("compressed data: " + compressedData.ToString(" ", "x"));
|
||||
|
||||
byte[] decompressedData = compressedData;
|
||||
if (CompressionModule != null)
|
||||
{
|
||||
decompressedData = CompressionModule.Decompress(compressedData);
|
||||
}
|
||||
_decompressedData = decompressedData;
|
||||
Console.WriteLine("decompressed data: " + decompressedData.ToString(" ", "x"));
|
||||
}
|
||||
|
||||
if (offset + length > _decompressedData.Length)
|
||||
{
|
||||
Console.WriteLine(String.Format("embedded file offset: {0}", Offset));
|
||||
Console.WriteLine(String.Format("requested offset: {0}", offset));
|
||||
Console.WriteLine(String.Format("requested length: {0}", length));
|
||||
Console.WriteLine(String.Format("actual stream length: {0}", _decompressedData.Length));
|
||||
throw new ArgumentOutOfRangeException("offset + length", "embedded file offset + requested offset + requested length extends past the actual length of the underlying stream");
|
||||
}
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Array.Copy(_decompressedData, offset, data, 0, data.Length);
|
||||
return data;
|
||||
}
|
||||
|
||||
public CompressedEmbeddedFileSource(Stream stream, long offset, long compressedLength, long decompressedLength) : base(stream, offset, decompressedLength)
|
||||
{
|
||||
CompressedLength = compressedLength;
|
||||
DecompressedLength = decompressedLength;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
public class EmbeddedFileSource : FileSource
|
||||
{
|
||||
public Stream Stream { get; }
|
||||
public long Offset { get; set; }
|
||||
|
||||
protected virtual long ActualLength { get; }
|
||||
|
||||
protected override long GetLengthInternal()
|
||||
{
|
||||
return ActualLength;
|
||||
}
|
||||
protected override byte[] GetDataInternal(long offset, long length)
|
||||
{
|
||||
if (Offset + offset + length >= Stream.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("embedded file offset + requested offset + requested length extends past the actual length of the underlying stream");
|
||||
}
|
||||
|
||||
Stream.Seek(Offset + offset, SeekOrigin.Begin);
|
||||
|
||||
byte[] data = new byte[length];
|
||||
Stream.Read(data, 0, data.Length);
|
||||
return data;
|
||||
}
|
||||
|
||||
public EmbeddedFileSource(Stream stream, long offset, long length)
|
||||
{
|
||||
Stream = stream;
|
||||
Offset = offset;
|
||||
ActualLength = length;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
//
|
||||
// StreamFileSource.cs - provides a FileSource for retrieving file data from a System.IO.Stream
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2011-2024 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a <see cref="FileSource" /> for retrieving file data from a <see cref="MemoryAccessor" />.
|
||||
/// </summary>
|
||||
public class StreamFileSource : FileSource
|
||||
{
|
||||
public Stream BaseStream { get; set; }
|
||||
public StreamFileSource(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
|
||||
protected override byte[] GetDataInternal(long offset, long length)
|
||||
{
|
||||
byte[] buffer = new byte[length];
|
||||
try
|
||||
{
|
||||
if (offset + length > BaseStream.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("offset + length is out of range");
|
||||
}
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
// continue anyway
|
||||
}
|
||||
|
||||
BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
BaseStream.Read(buffer, 0, (int)length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
protected override long GetLengthInternal()
|
||||
{
|
||||
return BaseStream.Length;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemCustomDetailCollection
|
||||
{
|
||||
private struct _item
|
||||
{
|
||||
public string id;
|
||||
public string title;
|
||||
}
|
||||
|
||||
private Dictionary<string, _item> _dict = new Dictionary<string, _item>();
|
||||
|
||||
public void Add(string id, string title)
|
||||
{
|
||||
_item item = new _item();
|
||||
item.id = id;
|
||||
item.title = title;
|
||||
_dict[id] = item;
|
||||
}
|
||||
public bool Contains(string id)
|
||||
{
|
||||
return _dict.ContainsKey(id);
|
||||
}
|
||||
public string GetTitle(string id)
|
||||
{
|
||||
_item item = _dict[id];
|
||||
return item.title;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemFile : FileSystemItem
|
||||
{
|
||||
public FileSource? Source { get; set; } = null;
|
||||
|
||||
public DateTime? ModificationTimestamp { get; set; } = null;
|
||||
|
||||
public Dictionary<string, object> CustomDetails { get; } = new Dictionary<string, object>();
|
||||
|
||||
public long Size
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Source == null)
|
||||
return 0;
|
||||
return Source.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemFolder : FileSystemItem, IFileSystemItemContainer
|
||||
{
|
||||
|
||||
public FileSystemItemCollection Items { get; }
|
||||
|
||||
public FileSystemFolder()
|
||||
{
|
||||
Items = new FileSystemItemCollection(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemItem
|
||||
{
|
||||
public FileSystemObjectModel FileSystem { get { return Parent?.FileSystem; } }
|
||||
public string? Name { get; set; } = null;
|
||||
public IFileSystemItemContainer? Parent { get; internal set; }
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
|
||||
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemItemCollection
|
||||
: System.Collections.ObjectModel.Collection<FileSystemItem>
|
||||
{
|
||||
public IFileSystemItemContainer Parent { get; }
|
||||
public FileSystemItemCollection(IFileSystemItemContainer parent)
|
||||
{
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return this[filename] != null;
|
||||
}
|
||||
public FileSystemItem? this[string filename]
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (FileSystemItem item in this)
|
||||
{
|
||||
if (item.Name == filename)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
this[i].Parent = null;
|
||||
}
|
||||
base.ClearItems();
|
||||
}
|
||||
protected override void InsertItem(int index, FileSystemItem item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
item.Parent = Parent;
|
||||
}
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
this[index].Parent = null;
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
|
||||
|
||||
public FileSystemFolder AddFolder(string name)
|
||||
{
|
||||
string[] path = name.Split(Parent.FileSystem.PathSeparators, StringSplitOptions.None);
|
||||
FileSystemFolder parent = null;
|
||||
for (int i = 0; i < path.Length; i++)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
parent = this[path[i]] as FileSystemFolder;
|
||||
if (parent == null)
|
||||
{
|
||||
FileSystemFolder f = new FileSystemFolder();
|
||||
f.Name = path[i];
|
||||
Add(f);
|
||||
parent = f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FileSystemFolder new_parent = parent.Items[path[i]] as FileSystemFolder;
|
||||
if (new_parent == null)
|
||||
{
|
||||
new_parent = new FileSystemFolder();
|
||||
new_parent.Name = path[i];
|
||||
parent.Items.Add(new_parent);
|
||||
}
|
||||
parent = new_parent;
|
||||
}
|
||||
if (parent == null) throw new DirectoryNotFoundException();
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
public FileSystemFile AddFile(string name, FileSource? source = null)
|
||||
{
|
||||
if (name == null) name = String.Empty;
|
||||
string[] path = name.Split(Parent.FileSystem.PathSeparators, StringSplitOptions.None);
|
||||
FileSystemFolder parent = null;
|
||||
for (int i = 0; i < path.Length - 1; i++)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
if (Contains(path[i]))
|
||||
{
|
||||
parent = this[path[i]] as FileSystemFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = AddFolder(path[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent.Items.Contains(path[i]))
|
||||
{
|
||||
parent = parent.Items[path[i]] as FileSystemFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = parent.Items.AddFolder(path[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
throw new System.IO.DirectoryNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
FileSystemFile file = new FileSystemFile();
|
||||
file.Name = path[path.Length - 1];
|
||||
file.Source = source;
|
||||
if (parent == null)
|
||||
{
|
||||
Add(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.Items.Add(file);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public FileSystemFile[] GetAllFiles()
|
||||
{
|
||||
List<FileSystemFile> list = new List<FileSystemFile>();
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i] is FileSystemFile Peter)
|
||||
{
|
||||
list.Add(Peter);
|
||||
}
|
||||
else if (this[i] is FileSystemFolder folder)
|
||||
{
|
||||
FileSystemFile[] files2 = folder.Items.GetAllFiles();
|
||||
list.AddRange(files2);
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public FileSystemFile[] GetFiles()
|
||||
{
|
||||
List<FileSystemFile> list = new List<FileSystemFile>();
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i] is FileSystemFile Peter)
|
||||
{
|
||||
list.Add(Peter);
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public FileSystemFolder[] GetFolders()
|
||||
{
|
||||
List<FileSystemFolder> list = new List<FileSystemFolder>();
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i] is FileSystemFolder folder)
|
||||
{
|
||||
list.Add(folder);
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public class FileSystemObjectModel : ObjectModel, IFileSystemItemContainer
|
||||
{
|
||||
public FileSystemObjectModel FileSystem { get { return this; } }
|
||||
public FileSystemItemCollection Items { get; }
|
||||
public FileSystemObjectModel()
|
||||
{
|
||||
Items = new FileSystemItemCollection(this);
|
||||
}
|
||||
|
||||
public FileSystemCustomDetailCollection CustomDetails { get; } = new FileSystemCustomDetailCollection();
|
||||
|
||||
public string[] PathSeparators { get; set; } = { "/", "\\" }; // System.IO.Path.DirectorySeparatorChar.ToString(), System.IO.Path.AltDirectorySeparatorChar.ToString() };
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
|
||||
public interface IFileSystemItemContainer
|
||||
{
|
||||
FileSystemObjectModel FileSystem { get; }
|
||||
FileSystemItemCollection Items { get; }
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// Mocha.NET is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Mocha.NET is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary;
|
||||
|
||||
public enum MochaAttributeType
|
||||
{
|
||||
Unknown = -1,
|
||||
None = 0,
|
||||
Text = 1,
|
||||
Boolean = 2,
|
||||
Numeric = 3,
|
||||
Date = 4
|
||||
}
|
||||
@ -0,0 +1,659 @@
|
||||
using MBS.Editor.Core;
|
||||
using MBS.Editor.Core.IO;
|
||||
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
using Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary;
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary;
|
||||
|
||||
public class MochaBinaryDataFormat : SlickBinaryDataFormat
|
||||
{
|
||||
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeLoadInternal(objectModels);
|
||||
objectModels.Push(new FileSystemObjectModel());
|
||||
}
|
||||
|
||||
private struct LIBRARY_INFO
|
||||
{
|
||||
public int libraryReferenceCount;
|
||||
public int instanceCount;
|
||||
public int attributeValueCount;
|
||||
public int relationshipCount;
|
||||
}
|
||||
private struct INSTANCE_INFO
|
||||
{
|
||||
public int instanceIndex;
|
||||
public int attributeValueCount;
|
||||
}
|
||||
|
||||
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.AfterLoadInternal(objectModels);
|
||||
|
||||
if (objectModels.Count < 2) throw new ObjectModelNotSupportedException("must have a FileSystemObjectModel and a MochaClassLibraryObjectModel in the stack");
|
||||
|
||||
FileSystemObjectModel fsom = (objectModels.Pop() as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
MochaClassLibraryObjectModel mcl = (objectModels.Pop() as MochaClassLibraryObjectModel);
|
||||
if (mcl == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
List<Guid> _instanceGuids = new List<Guid>();
|
||||
List<string> _stringTable = new List<string>();
|
||||
|
||||
LIBRARY_INFO[] library_info = null;
|
||||
|
||||
#region Libraries
|
||||
{
|
||||
FileSystemFile fLibraries = fsom.Items.FindFile("Libraries");
|
||||
using (MemoryStream ms = new MemoryStream(fLibraries.Source.GetData()))
|
||||
{
|
||||
Reader reader = new Reader(ms);
|
||||
int libraryCount = reader.ReadInt32();
|
||||
library_info = new LIBRARY_INFO[libraryCount];
|
||||
|
||||
for (int i = 0; i < libraryCount; i++)
|
||||
{
|
||||
MochaLibrary library = new MochaLibrary();
|
||||
library.ID = reader.ReadGuid();
|
||||
library_info[i].libraryReferenceCount = reader.ReadInt32();
|
||||
library_info[i].instanceCount = reader.ReadInt32();
|
||||
// library_info[i].attributeValueCount = ma.Reader.ReadInt32();
|
||||
library_info[i].relationshipCount = reader.ReadInt32();
|
||||
|
||||
mcl.Libraries.Add(library);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Guid Table
|
||||
{
|
||||
File fGlobalIdentifiers = fsom.FindFile("GlobalIdentifiers");
|
||||
using (MemoryAccessor ma = new MemoryAccessor(fGlobalIdentifiers.GetData()))
|
||||
{
|
||||
int instanceCount = ma.Reader.ReadInt32();
|
||||
for (int i = 0; i < instanceCount; i++)
|
||||
{
|
||||
_instanceGuids.Add(ma.Reader.ReadGuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region String Table
|
||||
{
|
||||
File f = fsom.FindFile("StringTable");
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
int stringTableCount = ma.Reader.ReadInt32();
|
||||
for (int i = 0; i < stringTableCount; i++)
|
||||
{
|
||||
string value = ma.Reader.ReadNullTerminatedString();
|
||||
_stringTable.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
INSTANCE_INFO[] instance_info = null;
|
||||
#region Instances
|
||||
{
|
||||
File f = fsom.FindFile("Instances");
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
int instance_info_offset = 0; // fixme: this should not be needed
|
||||
int libraryReferenceCount = ma.Reader.ReadInt32();
|
||||
for (int j = 0; j < libraryReferenceCount; j++)
|
||||
{
|
||||
int libraryIndex = ma.Reader.ReadInt32();
|
||||
Guid libraryID = _instanceGuids[libraryIndex];
|
||||
mcl.Libraries[i].LibraryReferences.Add(libraryID);
|
||||
}
|
||||
int instanceCount = ma.Reader.ReadInt32();
|
||||
// if (instance_info == null)
|
||||
{
|
||||
instance_info = new INSTANCE_INFO[instanceCount];
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
instance_info_offset = instance_info.Length;
|
||||
Array.Resize<INSTANCE_INFO>(ref instance_info, instance_info.Length + instanceCount);
|
||||
}
|
||||
*/
|
||||
for (int j = 0; j < instanceCount; j++)
|
||||
{
|
||||
instance_info[j + instance_info_offset].instanceIndex = ma.Reader.ReadInt32();
|
||||
instance_info[j + instance_info_offset].attributeValueCount = ma.Reader.ReadInt32();
|
||||
MochaInstanceFlags flags = (MochaInstanceFlags)ma.Reader.ReadInt32();
|
||||
|
||||
int? index = null;
|
||||
if ((flags & MochaInstanceFlags.HasIndex) == MochaInstanceFlags.HasIndex)
|
||||
{
|
||||
index = ma.Reader.ReadInt32();
|
||||
}
|
||||
|
||||
MochaInstance inst = new MochaInstance();
|
||||
inst.ID = _instanceGuids[instance_info[j + instance_info_offset].instanceIndex];
|
||||
inst.Index = index;
|
||||
mcl.Libraries[i].Instances.Add(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Attributes
|
||||
{
|
||||
File f = fsom.FindFile("Attributes");
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < mcl.Libraries[i].Instances.Count; j++)
|
||||
{
|
||||
for (int k = 0; k < instance_info[j].attributeValueCount; k++)
|
||||
{
|
||||
int attributeInstanceIndex = ma.Reader.ReadInt32();
|
||||
|
||||
MochaAttributeValue val = new MochaAttributeValue();
|
||||
val.AttributeInstanceID = _instanceGuids[attributeInstanceIndex];
|
||||
|
||||
val.Value = ReadMochaAttributeValue(ma.Reader, _stringTable);
|
||||
mcl.Libraries[i].Instances[j].AttributeValues.Add(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Relationships
|
||||
{
|
||||
File f = fsom.FindFile("Relationships");
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < library_info[i].relationshipCount; j++)
|
||||
{
|
||||
int relationshipIndex = ma.Reader.ReadInt32();
|
||||
int sourceInstanceIndex = ma.Reader.ReadInt32();
|
||||
|
||||
MochaRelationship rel = new MochaRelationship();
|
||||
rel.RelationshipInstanceID = _instanceGuids[relationshipIndex];
|
||||
rel.SourceInstanceID = _instanceGuids[sourceInstanceIndex];
|
||||
|
||||
int targetInstanceCount = ma.Reader.ReadInt32();
|
||||
for (int k = 0; k < targetInstanceCount; k++)
|
||||
{
|
||||
int instanceIndex = ma.Reader.ReadInt32();
|
||||
rel.DestinationInstanceIDs.Add(_instanceGuids[instanceIndex]);
|
||||
}
|
||||
|
||||
mcl.Libraries[i].Relationships.Add(rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tenants
|
||||
{
|
||||
File f = fsom.FindFile("Tenants");
|
||||
if (f != null)
|
||||
{
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
int tenantCount = ma.Reader.ReadInt32();
|
||||
for (int i = 0; i < tenantCount; i++)
|
||||
{
|
||||
int instanceIndex = ma.Reader.ReadInt32();
|
||||
Guid instanceGuid = _instanceGuids[instanceIndex];
|
||||
|
||||
int tenantNameIndex = ma.Reader.ReadInt32();
|
||||
string tenantName = _stringTable[tenantNameIndex];
|
||||
|
||||
MochaTenant tenant = new MochaTenant();
|
||||
tenant.ID = instanceGuid;
|
||||
tenant.Name = tenantName;
|
||||
|
||||
int libraryReferenceCount = ma.Reader.ReadInt32();
|
||||
for (int j = 0; j < libraryReferenceCount; j++)
|
||||
{
|
||||
int libraryIndex = ma.Reader.ReadInt32();
|
||||
Guid libraryID = _instanceGuids[libraryIndex];
|
||||
tenant.LibraryReferences.Add(libraryID);
|
||||
}
|
||||
|
||||
int instanceCount = ma.Reader.ReadInt32();
|
||||
for (int j = 0; j < instanceCount; j++)
|
||||
{
|
||||
int instanceIndex2 = ma.Reader.ReadInt32();
|
||||
MochaInstance inst = new MochaInstance();
|
||||
inst.ID = _instanceGuids[instanceIndex2];
|
||||
tenant.Instances.Add(inst);
|
||||
}
|
||||
|
||||
int relationshipCount = ma.Reader.ReadInt32();
|
||||
for (int j = 0; j < relationshipCount; j++)
|
||||
{
|
||||
int sourceInex = ma.Reader.ReadInt32();
|
||||
Guid ssource = _instanceGuids[sourceInex];
|
||||
int relationshipInex = ma.Reader.ReadInt32();
|
||||
Guid relati = _instanceGuids[relationshipInex];
|
||||
|
||||
MochaRelationship rel = new MochaRelationship();
|
||||
rel.SourceInstanceID = ssource;
|
||||
rel.RelationshipInstanceID = relati;
|
||||
|
||||
int count = ma.Reader.ReadInt32();
|
||||
for (int k = 0; k < count; k++)
|
||||
{
|
||||
int targetIndex = ma.Reader.ReadInt32();
|
||||
Guid targ = _instanceGuids[targetIndex];
|
||||
rel.DestinationInstanceIDs.Add(targ);
|
||||
}
|
||||
|
||||
tenant.Relationships.Add(rel);
|
||||
}
|
||||
mcl.Tenants.Add(tenant);
|
||||
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Journal
|
||||
{
|
||||
// journal is present in MCX / MCD (application, data files)
|
||||
// is an opcode based format
|
||||
// eg. 0x01 = create instance, 0x02 = delete instance
|
||||
// 0x04 = set attribute value, 0x05 = delete attribute value
|
||||
// 0x08 = create relationship, 0x09 = remove relationship
|
||||
|
||||
File f = fsom.FindFile("Journal");
|
||||
if (f != null)
|
||||
{
|
||||
using (MemoryAccessor ma = new MemoryAccessor(f.GetData()))
|
||||
{
|
||||
for (int i = 0; i < mcl.Tenants.Count; i++)
|
||||
{
|
||||
bool readingTenant = true;
|
||||
while (readingTenant)
|
||||
{
|
||||
MochaOpcode opcode = (MochaOpcode)ma.Reader.ReadByte();
|
||||
switch (opcode)
|
||||
{
|
||||
case MochaOpcode.BeginTenant:
|
||||
{
|
||||
int tenantNameIndex = ma.Reader.ReadInt32();
|
||||
break;
|
||||
}
|
||||
case MochaOpcode.EndTenant:
|
||||
{
|
||||
readingTenant = false; // exit outer loop
|
||||
break;
|
||||
}
|
||||
case MochaOpcode.CreateInstance:
|
||||
{
|
||||
int guidIndex = ma.Reader.ReadInt32();
|
||||
|
||||
MochaInstance inst = new MochaInstance();
|
||||
inst.ID = _instanceGuids[guidIndex];
|
||||
mcl.Tenants[i].Instances.Add(inst);
|
||||
break;
|
||||
}
|
||||
case MochaOpcode.CreateRelationship:
|
||||
case MochaOpcode.RemoveRelationship:
|
||||
{
|
||||
int relationshipIndex = ma.Reader.ReadInt32();
|
||||
int sourceInstanceIndex = ma.Reader.ReadInt32();
|
||||
|
||||
MochaRelationship rel = new MochaRelationship();
|
||||
rel.RelationshipInstanceID = _instanceGuids[relationshipIndex];
|
||||
rel.SourceInstanceID = _instanceGuids[sourceInstanceIndex];
|
||||
|
||||
int targetInstanceCount = ma.Reader.ReadInt32();
|
||||
for (int k = 0; k < targetInstanceCount; k++)
|
||||
{
|
||||
int instanceIndex = ma.Reader.ReadInt32();
|
||||
rel.DestinationInstanceIDs.Add(_instanceGuids[instanceIndex]);
|
||||
}
|
||||
|
||||
if (opcode == MochaOpcode.RemoveRelationship)
|
||||
{
|
||||
rel.Remove = true;
|
||||
}
|
||||
|
||||
mcl.Tenants[i].Relationships.Add(rel);
|
||||
break;
|
||||
}
|
||||
case MochaOpcode.SetAttributeValue:
|
||||
{
|
||||
int instanceIndex = ma.Reader.ReadInt32();
|
||||
Guid instanceID = _instanceGuids[instanceIndex];
|
||||
|
||||
int attributeIndex = ma.Reader.ReadInt32();
|
||||
Guid attributeInstanceID = _instanceGuids[attributeIndex];
|
||||
|
||||
object value = ReadMochaAttributeValue(ma.Reader, _stringTable);
|
||||
|
||||
MochaAttributeValue mav = new MochaAttributeValue();
|
||||
mav.AttributeInstanceID = attributeInstanceID;
|
||||
mav.Value = value;
|
||||
mcl.Tenants[i].Instances[instanceID].AttributeValues.Add(mav);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
private object ReadMochaAttributeValue(Reader reader, List<string>_stringTable)
|
||||
{
|
||||
MochaAttributeType attributeType = (MochaAttributeType)reader.ReadInt32();
|
||||
switch (attributeType)
|
||||
{
|
||||
case MochaAttributeType.None:
|
||||
{
|
||||
return null;
|
||||
}
|
||||
case MochaAttributeType.Text:
|
||||
{
|
||||
int stringTableIndex = reader.ReadInt32();
|
||||
string value = _stringTable[stringTableIndex];
|
||||
return value;
|
||||
}
|
||||
case MochaAttributeType.Boolean:
|
||||
{
|
||||
bool value = reader.ReadBoolean();
|
||||
return value;
|
||||
}
|
||||
case MochaAttributeType.Date:
|
||||
{
|
||||
DateTime value = reader.ReadDateTime();
|
||||
return value;
|
||||
}
|
||||
case MochaAttributeType.Numeric:
|
||||
{
|
||||
decimal value = reader.ReadDecimal();
|
||||
return value;
|
||||
}
|
||||
case MochaAttributeType.Unknown:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
|
||||
{
|
||||
base.BeforeSaveInternal(objectModels);
|
||||
|
||||
FileNameSize = 32;
|
||||
|
||||
MochaClassLibraryObjectModel mcl = (objectModels.Pop() as MochaClassLibraryObjectModel);
|
||||
if (mcl == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
FileSystemObjectModel fsom = new FileSystemObjectModel();
|
||||
|
||||
List<Guid> _instanceIndices = new List<Guid>();
|
||||
List<string> _stringTable = new List<string>();
|
||||
|
||||
#region Libraries
|
||||
{
|
||||
File f = fsom.AddFile("Libraries");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
ma.Writer.WriteInt32(mcl.Libraries.Count);
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
ma.Writer.WriteGuid(mcl.Libraries[i].ID);
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].LibraryReferences.Count);
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Instances.Count);
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Relationships.Count);
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
#region Instances
|
||||
{
|
||||
File f = fsom.AddFile("Instances");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].LibraryReferences.Count);
|
||||
for (int j = 0; j < mcl.Libraries[i].LibraryReferences.Count; j++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].LibraryReferences[j]));
|
||||
}
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Instances.Count);
|
||||
for (int j = 0; j < mcl.Libraries[i].Instances.Count; j++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].Instances[j].ID));
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Instances[j].AttributeValues.Count);
|
||||
|
||||
MochaInstanceFlags flags = MochaInstanceFlags.None;
|
||||
if (mcl.Libraries[i].Instances[j].Index != null)
|
||||
{
|
||||
flags |= MochaInstanceFlags.HasIndex;
|
||||
}
|
||||
ma.Writer.WriteInt32((int)flags);
|
||||
|
||||
if ((flags & MochaInstanceFlags.HasIndex) == MochaInstanceFlags.HasIndex)
|
||||
{
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Instances[j].Index.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
#region Attributes
|
||||
{
|
||||
File f = fsom.AddFile("Attributes");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
/*
|
||||
writer.WriteInt32(mcl.Libraries[i].Metadata.Count);
|
||||
for (int j = 0; j < mcl.Libraries[i].Metadata.Count; j++)
|
||||
{
|
||||
writer.WriteNullTerminatedString(mcl.Libraries[i].Metadata[j].Name);
|
||||
writer.WriteNullTerminatedString(mcl.Libraries[i].Metadata[j].Value);
|
||||
}
|
||||
*/
|
||||
for (int j = 0; j < mcl.Libraries[i].Instances.Count; j++)
|
||||
{
|
||||
for (int k = 0; k < mcl.Libraries[i].Instances[j].AttributeValues.Count; k++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].Instances[j].AttributeValues[k].AttributeInstanceID));
|
||||
|
||||
WriteMochaAttributeValue(ma.Writer, _stringTable, mcl.Libraries[i].Instances[j].AttributeValues[k].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
#region Relationships
|
||||
{
|
||||
File f = fsom.AddFile("Relationships");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
for (int i = 0; i < mcl.Libraries.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < mcl.Libraries[i].Relationships.Count; j++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].RelationshipInstanceID));
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].SourceInstanceID));
|
||||
|
||||
ma.Writer.WriteInt32(mcl.Libraries[i].Relationships[j].DestinationInstanceIDs.Count);
|
||||
for (int k = 0; k < mcl.Libraries[i].Relationships[j].DestinationInstanceIDs.Count; k++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, mcl.Libraries[i].Relationships[j].DestinationInstanceIDs[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tenants
|
||||
{
|
||||
if (mcl.Tenants.Count > 0)
|
||||
{
|
||||
File f = fsom.AddFile("Tenants");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
ma.Writer.WriteInt32(mcl.Tenants.Count);
|
||||
foreach (MochaTenant tenant in mcl.Tenants)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.ID));
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<string>(_stringTable, tenant.Name));
|
||||
|
||||
ma.Writer.WriteInt32(tenant.LibraryReferences.Count);
|
||||
for (int i = 0; i < tenant.LibraryReferences.Count; i++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.LibraryReferences[i]));
|
||||
}
|
||||
|
||||
ma.Writer.WriteInt32(tenant.Instances.Count);
|
||||
for (int i = 0; i < tenant.Instances.Count; i++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Instances[i].ID));
|
||||
}
|
||||
ma.Writer.WriteInt32(tenant.Relationships.Count);
|
||||
for (int i = 0; i < tenant.Relationships.Count; i++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Relationships[i].SourceInstanceID));
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Relationships[i].RelationshipInstanceID));
|
||||
ma.Writer.WriteInt32(tenant.Relationships[i].DestinationInstanceIDs.Count);
|
||||
for (int j = 0; j < tenant.Relationships[i].DestinationInstanceIDs.Count; j++)
|
||||
{
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Relationships[i].DestinationInstanceIDs[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Journal
|
||||
{
|
||||
if (mcl.Tenants.Count > 0)
|
||||
{
|
||||
File f = fsom.AddFile("Journal");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
foreach (MochaTenant tenant in mcl.Tenants)
|
||||
{
|
||||
ma.Writer.WriteByte((byte)MochaOpcode.BeginTenant);
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<string>(_stringTable, tenant.Name));
|
||||
for (int i = 0; i < tenant.Instances.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < tenant.Instances[i].AttributeValues.Count; j++)
|
||||
{
|
||||
ma.Writer.WriteByte((byte)MochaOpcode.SetAttributeValue);
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Instances[i].ID));
|
||||
ma.Writer.WriteInt32(AddOrUpdateLookupTable<Guid>(_instanceIndices, tenant.Instances[i].AttributeValues[j].AttributeInstanceID));
|
||||
|
||||
WriteMochaAttributeValue(ma.Writer, _stringTable, tenant.Instances[i].AttributeValues[j].Value);
|
||||
}
|
||||
}
|
||||
ma.Writer.WriteByte((byte)MochaOpcode.EndTenant);
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Guid Table
|
||||
{
|
||||
File f = fsom.AddFile("GlobalIdentifiers");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
ma.Writer.WriteInt32(_instanceIndices.Count);
|
||||
foreach (Guid id in _instanceIndices)
|
||||
{
|
||||
ma.Writer.WriteGuid(id);
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
#region String Table
|
||||
{
|
||||
File f = fsom.AddFile("StringTable");
|
||||
MemoryAccessor ma = new MemoryAccessor();
|
||||
ma.Writer.WriteInt32(_stringTable.Count);
|
||||
foreach (string id in _stringTable)
|
||||
{
|
||||
ma.Writer.WriteNullTerminatedString(id);
|
||||
}
|
||||
ma.Close();
|
||||
f.SetData(ma.ToArray());
|
||||
}
|
||||
#endregion
|
||||
|
||||
objectModels.Push(fsom);
|
||||
}
|
||||
|
||||
private void WriteMochaAttributeValue(Writer writer, List<string> _stringTable, object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.None);
|
||||
}
|
||||
else if (value is string)
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.Text);
|
||||
writer.WriteInt32(AddOrUpdateLookupTable<string>(_stringTable, value as string));
|
||||
}
|
||||
else if (value is bool)
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.Boolean);
|
||||
writer.WriteBoolean((bool)value);
|
||||
}
|
||||
else if (value is DateTime)
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.Date);
|
||||
writer.WriteDateTime((DateTime)value);
|
||||
}
|
||||
else if (value is decimal || value is int)
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.Numeric);
|
||||
|
||||
// ...... eww.
|
||||
writer.WriteDecimal(Decimal.Parse(value.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteInt32((int)MochaAttributeType.Unknown);
|
||||
writer.WriteObject(value);
|
||||
}
|
||||
}
|
||||
|
||||
private int AddOrUpdateLookupTable<T1>(List<T1> dict, T1 id)
|
||||
{
|
||||
if (!dict.Contains(id))
|
||||
{
|
||||
dict.Add(id);
|
||||
}
|
||||
return dict.IndexOf(id);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// Mocha.NET is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Mocha.NET is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary;
|
||||
|
||||
|
||||
[Flags()]
|
||||
public enum MochaInstanceFlags
|
||||
{
|
||||
None = 0,
|
||||
HasIndex = 1
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// Mocha.NET is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Mocha.NET is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary;
|
||||
|
||||
public enum MochaOpcode : byte
|
||||
{
|
||||
CreateInstance = 0x01,
|
||||
DeleteInstance = 0x02,
|
||||
|
||||
SetAttributeValue = 0x04,
|
||||
DeleteAttributeValue = 0x05,
|
||||
|
||||
CreateRelationship = 0x08,
|
||||
RemoveRelationship = 0x09,
|
||||
|
||||
BeginTenant = 0x0A,
|
||||
EndTenant = 0x8A
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
//
|
||||
// IMochaStore.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public interface IMochaStore
|
||||
{
|
||||
List<Guid> LibraryReferences { get; }
|
||||
MochaInstance.MochaInstanceCollection Instances { get; }
|
||||
MochaRelationship.MochaRelationshipCollection Relationships { get; }
|
||||
|
||||
Guid DefaultObjectSourceID { get; }
|
||||
MochaInstance FindInstance(Guid id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
//
|
||||
// MochaAttributeValue.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaAttributeValue : ICloneable
|
||||
{
|
||||
public class MochaAttributeValueCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaAttributeValue>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Guid AttributeInstanceID { get; set; }
|
||||
public object Value { get; set; }
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaAttributeValue clone = new MochaAttributeValue();
|
||||
clone.AttributeInstanceID = AttributeInstanceID;
|
||||
if (Value is ICloneable)
|
||||
{
|
||||
clone.Value = (Value as ICloneable).Clone();
|
||||
}
|
||||
else
|
||||
{
|
||||
clone.Value = Value;
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,112 @@
|
||||
//
|
||||
// MochaClassLibrary.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using MBS.Editor.Core;
|
||||
using Mocha.Core;
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaClassLibraryObjectModel : ObjectModel
|
||||
{
|
||||
public MochaTenant.MochaTenantCollection Tenants { get; } = new MochaTenant.MochaTenantCollection();
|
||||
public MochaLibrary.MochaLibraryCollection Libraries { get; } = new MochaLibrary.MochaLibraryCollection();
|
||||
|
||||
/*
|
||||
public override void Clear()
|
||||
{
|
||||
Libraries.Clear();
|
||||
}
|
||||
|
||||
public override void CopyTo(ObjectModel where)
|
||||
{
|
||||
MochaClassLibraryObjectModel clone = (where as MochaClassLibraryObjectModel);
|
||||
if (clone == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
for (int i = 0; i < Libraries.Count; i++)
|
||||
{
|
||||
clone.Libraries.Add(Libraries[i].Clone() as MochaLibrary);
|
||||
}
|
||||
for (int i = 0; i < Tenants.Count; i++)
|
||||
{
|
||||
clone.Tenants.Add(Tenants[i].Clone() as MochaTenant);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public MochaInstance FindInstance(Guid id)
|
||||
{
|
||||
return FindInstance(id, out IMochaStore store);
|
||||
}
|
||||
public MochaInstance FindInstance(Guid id, out IMochaStore store)
|
||||
{
|
||||
for (int i = 0; i < Libraries.Count; i++)
|
||||
{
|
||||
MochaInstance inst = Libraries[i].Instances[id];
|
||||
if (inst != null)
|
||||
{
|
||||
store = Libraries[i];
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Tenants.Count; i++)
|
||||
{
|
||||
MochaInstance inst = Tenants[i].Instances[id];
|
||||
if (inst != null)
|
||||
{
|
||||
store = Tenants[i];
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
|
||||
store = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
public MochaRelationship FindRelationship(RelationshipKey relationshipKey)
|
||||
{
|
||||
return FindRelationship(relationshipKey, out IMochaStore store);
|
||||
}
|
||||
public MochaRelationship FindRelationship(RelationshipKey relationshipKey, out IMochaStore store)
|
||||
{
|
||||
for (int i = 0; i < Libraries.Count; i++)
|
||||
{
|
||||
MochaRelationship rel = Libraries[i].Relationships[relationshipKey];
|
||||
if (rel != null)
|
||||
{
|
||||
store = Libraries[i];
|
||||
return rel;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Tenants.Count; i++)
|
||||
{
|
||||
MochaRelationship rel = Tenants[i].Relationships[relationshipKey];
|
||||
if (rel != null)
|
||||
{
|
||||
store = Tenants[i];
|
||||
return rel;
|
||||
}
|
||||
}
|
||||
|
||||
store = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
//
|
||||
// MochaInstance.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaInstance : ICloneable
|
||||
{
|
||||
public class MochaInstanceCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaInstance>
|
||||
{
|
||||
public MochaInstance this[Guid id]
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i].ID == id)
|
||||
return this[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public void Merge(MochaInstance item)
|
||||
{
|
||||
MochaInstance orig = this[item.ID];
|
||||
if (orig != null)
|
||||
{
|
||||
orig.Merge(item);
|
||||
return;
|
||||
}
|
||||
Add(item);
|
||||
}
|
||||
|
||||
public bool Contains(Guid id)
|
||||
{
|
||||
for (int i = 0; i < Count;i ++)
|
||||
{
|
||||
if (this[i].ID == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void Merge(MochaInstance item)
|
||||
{
|
||||
if (ID != item.ID)
|
||||
throw new InvalidOperationException("cannot merge two instances with different global identifiers");
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Guid ID { get; set; } = Guid.Empty;
|
||||
public int? Index { get; set; } = null;
|
||||
public MochaAttributeValue.MochaAttributeValueCollection AttributeValues { get; } = new MochaAttributeValue.MochaAttributeValueCollection();
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaInstance clone = new MochaInstance();
|
||||
clone.ID = ID;
|
||||
clone.Index = Index;
|
||||
for (int i = 0; i < AttributeValues.Count; i++)
|
||||
{
|
||||
clone.AttributeValues.Add(AttributeValues[i].Clone() as MochaAttributeValue);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
//
|
||||
// MochaLibrary.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaLibrary : ICloneable, IMochaStore
|
||||
{
|
||||
public class MochaLibraryCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaLibrary>
|
||||
{
|
||||
public MochaLibrary this[Guid id]
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i].ID == id)
|
||||
return this[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Merge(MochaLibrary item)
|
||||
{
|
||||
MochaLibrary orig = this[item.ID];
|
||||
if (orig != null)
|
||||
{
|
||||
orig.Merge(item);
|
||||
return;
|
||||
}
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void Merge(MochaLibrary item)
|
||||
{
|
||||
for (int i = 0; i < item.Metadata.Count; i++)
|
||||
{
|
||||
if (!Metadata.Contains(item.Metadata[i].Name))
|
||||
{
|
||||
Metadata.Add(item.Metadata[i]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < item.Instances.Count; i++)
|
||||
{
|
||||
Instances.Merge(item.Instances[i]);
|
||||
}
|
||||
for (int i = 0; i < item.Relationships.Count; i++)
|
||||
{
|
||||
Relationships.Merge(item.Relationships[i]);
|
||||
}
|
||||
for (int i = 0; i < item.LibraryReferences.Count; i++)
|
||||
{
|
||||
LibraryReferences.Add(item.LibraryReferences[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Guid ID { get; set; }
|
||||
public MochaLibraryMetadata.MochaLibraryMetadataCollection Metadata { get; } = new MochaLibraryMetadata.MochaLibraryMetadataCollection();
|
||||
|
||||
public MochaInstance.MochaInstanceCollection Instances { get; } = new MochaInstance.MochaInstanceCollection();
|
||||
public MochaRelationship.MochaRelationshipCollection Relationships { get; } = new MochaRelationship.MochaRelationshipCollection();
|
||||
public System.Collections.Generic.List<Guid> LibraryReferences { get; } = new System.Collections.Generic.List<Guid>();
|
||||
|
||||
public Guid DefaultObjectSourceID { get; set; }
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaLibrary clone = new MochaLibrary();
|
||||
clone.ID = ID;
|
||||
clone.DefaultObjectSourceID = DefaultObjectSourceID;
|
||||
for (int i = 0; i < Metadata.Count; i++)
|
||||
{
|
||||
clone.Metadata.Add(Metadata[i].Clone() as MochaLibraryMetadata);
|
||||
}
|
||||
for (int i = 0; i < Instances.Count; i++)
|
||||
{
|
||||
clone.Instances.Add(Instances[i].Clone() as MochaInstance);
|
||||
}
|
||||
for (int i = 0; i < Relationships.Count; i++)
|
||||
{
|
||||
clone.Relationships.Add(Relationships[i].Clone() as MochaRelationship);
|
||||
}
|
||||
for (int i = 0; i < LibraryReferences.Count; i++)
|
||||
{
|
||||
clone.LibraryReferences.Add(LibraryReferences[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
public MochaInstance FindInstance(Guid id)
|
||||
{
|
||||
if (Instances[id] != null)
|
||||
return Instances[id];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
//
|
||||
// MochaLibraryMetadata.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaLibraryMetadata : ICloneable
|
||||
{
|
||||
public class MochaLibraryMetadataCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaLibraryMetadata>
|
||||
{
|
||||
private Dictionary<string, MochaLibraryMetadata> _itemsByName = new Dictionary<string, MochaLibraryMetadata>();
|
||||
public MochaLibraryMetadata this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_itemsByName.ContainsKey(name))
|
||||
return _itemsByName[name];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public bool Contains(string name)
|
||||
{
|
||||
return _itemsByName.ContainsKey(name);
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
base.ClearItems();
|
||||
_itemsByName.Clear();
|
||||
}
|
||||
protected override void InsertItem(int index, MochaLibraryMetadata item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
_itemsByName[item.Name] = item;
|
||||
}
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
if (_itemsByName.ContainsKey(this[index].Name))
|
||||
_itemsByName.Remove(this[index].Name);
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
|
||||
public MochaLibraryMetadata(string name, string value)
|
||||
{
|
||||
Name = name;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaLibraryMetadata clone = new MochaLibraryMetadata(Name?.Clone() as string, Value?.Clone() as string);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
//
|
||||
// MochaRelationship.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mocha.Core;
|
||||
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaRelationship : ICloneable
|
||||
{
|
||||
public class MochaRelationshipCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaRelationship>
|
||||
{
|
||||
private Dictionary<RelationshipKey, MochaRelationship> _itemsByKey = new Dictionary<RelationshipKey, MochaRelationship>();
|
||||
public MochaRelationship this[RelationshipKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_itemsByKey.ContainsKey(key))
|
||||
return _itemsByKey[key];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
base.ClearItems();
|
||||
_itemsByKey.Clear();
|
||||
}
|
||||
protected override void InsertItem(int index, MochaRelationship item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
_itemsByKey[new RelationshipKey(item.SourceInstanceID, item.RelationshipInstanceID)] = item;
|
||||
}
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
_itemsByKey.Remove(new RelationshipKey(this[index].SourceInstanceID, this[index].RelationshipInstanceID));
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
|
||||
public void Merge(MochaRelationship item)
|
||||
{
|
||||
MochaRelationship orig = this[new RelationshipKey(item.SourceInstanceID, item.RelationshipInstanceID)];
|
||||
if (orig != null)
|
||||
{
|
||||
orig.Merge(item);
|
||||
return;
|
||||
}
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public Guid RelationshipInstanceID { get; set; }
|
||||
public Guid SourceInstanceID { get; set; }
|
||||
public List<Guid> DestinationInstanceIDs { get; set; } = new List<Guid>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="MochaRelationship"/> should be removed from the tenant.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if remove; otherwise, <c>false</c>.</value>
|
||||
public bool Remove { get; set; } = false;
|
||||
|
||||
private void Merge(MochaRelationship item)
|
||||
{
|
||||
if (!(SourceInstanceID == item.SourceInstanceID && RelationshipInstanceID == item.RelationshipInstanceID))
|
||||
throw new InvalidOperationException("cannot merge two instances with different (source and relationship) identifiers");
|
||||
|
||||
foreach (Guid id in item.DestinationInstanceIDs)
|
||||
DestinationInstanceIDs.Add(id);
|
||||
}
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaRelationship clone = new MochaRelationship();
|
||||
clone.RelationshipInstanceID = RelationshipInstanceID;
|
||||
clone.SourceInstanceID = SourceInstanceID;
|
||||
for (int i = 0; i < DestinationInstanceIDs.Count; i++)
|
||||
{
|
||||
clone.DestinationInstanceIDs.Add(DestinationInstanceIDs[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
//
|
||||
// MochaTenant.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace Mocha.Plugins.Libraries.MochaBinary.ObjectModels.MochaClassLibrary
|
||||
{
|
||||
public class MochaTenant : ICloneable, IMochaStore
|
||||
{
|
||||
public class MochaTenantCollection
|
||||
: System.Collections.ObjectModel.Collection<MochaTenant>
|
||||
{
|
||||
public MochaTenant this[Guid id]
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (MochaTenant tenant in this)
|
||||
{
|
||||
if (tenant.ID == id)
|
||||
return tenant;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public MochaTenant this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (MochaTenant tenant in this)
|
||||
{
|
||||
if (tenant.Name == name)
|
||||
return tenant;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public void Merge(MochaTenant tenant)
|
||||
{
|
||||
MochaTenant existing = this[tenant.ID];
|
||||
if (existing != null)
|
||||
{
|
||||
if (existing.Name == null && tenant.Name != null)
|
||||
{
|
||||
existing.Name = tenant.Name;
|
||||
}
|
||||
if (existing.DefaultObjectSourceID == Guid.Empty)
|
||||
existing.DefaultObjectSourceID = tenant.DefaultObjectSourceID;
|
||||
|
||||
foreach (Guid lref in tenant.LibraryReferences)
|
||||
{
|
||||
if (!existing.LibraryReferences.Contains(lref))
|
||||
existing.LibraryReferences.Add(lref);
|
||||
}
|
||||
|
||||
foreach (MochaInstance inst in tenant.Instances)
|
||||
{
|
||||
if (!existing.Instances.Contains(inst))
|
||||
{
|
||||
existing.Instances.Add(inst);
|
||||
}
|
||||
}
|
||||
foreach (MochaRelationship rel in tenant.Relationships)
|
||||
{
|
||||
if (!existing.Relationships.Contains(rel))
|
||||
{
|
||||
existing.Relationships.Add(rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Add(tenant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Guid ID { get; set; }
|
||||
public Guid DefaultObjectSourceID { get; set; }
|
||||
|
||||
public string Name { get; set; } = null;
|
||||
|
||||
public MochaLibraryMetadata.MochaLibraryMetadataCollection Metadata { get; } = new MochaLibraryMetadata.MochaLibraryMetadataCollection();
|
||||
|
||||
public MochaInstance.MochaInstanceCollection Instances { get; } = new MochaInstance.MochaInstanceCollection();
|
||||
public MochaRelationship.MochaRelationshipCollection Relationships { get; } = new MochaRelationship.MochaRelationshipCollection();
|
||||
public System.Collections.Generic.List<Guid> LibraryReferences { get; } = new System.Collections.Generic.List<Guid>();
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
MochaTenant clone = new MochaTenant();
|
||||
clone.ID = ID;
|
||||
clone.DefaultObjectSourceID = DefaultObjectSourceID;
|
||||
clone.Name = (Name.Clone() as string);
|
||||
|
||||
foreach (MochaLibraryMetadata item in Metadata)
|
||||
{
|
||||
clone.Metadata.Add(item.Clone() as MochaLibraryMetadata);
|
||||
}
|
||||
|
||||
foreach (MochaInstance item in Instances)
|
||||
{
|
||||
clone.Instances.Add(item.Clone() as MochaInstance);
|
||||
}
|
||||
foreach (MochaRelationship item in Relationships)
|
||||
{
|
||||
clone.Relationships.Add(item.Clone() as MochaRelationship);
|
||||
}
|
||||
foreach (Guid item in LibraryReferences)
|
||||
{
|
||||
clone.LibraryReferences.Add((Guid)item);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
public MochaInstance FindInstance(Guid id)
|
||||
{
|
||||
MochaInstance inst = Instances[id];
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// Mocha.NET is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Mocha.NET is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using MBS.Editor.Core;
|
||||
using MBS.Editor.Core.IO;
|
||||
using MBS.Editor.Core.ObjectModels.FileSystem;
|
||||
using MBS.Editor.Core.ObjectModels.FileSystem.FileSources;
|
||||
|
||||
public class SlickBinaryDataFormat : DataFormat
|
||||
{
|
||||
public SlickBinaryDataFormat()
|
||||
{
|
||||
}
|
||||
|
||||
public int FileNameSize { get; set; } = 128;
|
||||
|
||||
protected override void LoadInternal(ObjectModel objectModel, Stream stream)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
Reader reader = new Reader(stream);
|
||||
string signature = reader.ReadFixedLengthString(8);
|
||||
if (!signature.Equals("slick!\0\0"))
|
||||
throw new InvalidDataFormatException("");
|
||||
|
||||
float version = reader.ReadSingle();
|
||||
if (version != 1.0f)
|
||||
throw new InvalidDataFormatException();
|
||||
|
||||
FileNameSize = reader.ReadInt32();
|
||||
|
||||
int fileCount = reader.ReadInt32();
|
||||
for (int i = 0; i < fileCount; i++)
|
||||
{
|
||||
string fileName = reader.ReadFixedLengthString(FileNameSize); // .TrimNull();
|
||||
int q = -1;
|
||||
if ((q = fileName.IndexOf('\0')) != -1)
|
||||
{
|
||||
fileName = fileName.Substring(0, q);
|
||||
}
|
||||
|
||||
int offset = reader.ReadInt32();
|
||||
int length = reader.ReadInt32();
|
||||
|
||||
FileSystemFile file = fsom.Items.AddFile(fileName);
|
||||
file.Source = new EmbeddedFileSource(stream, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel, Stream stream)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null)
|
||||
throw new ObjectModelNotSupportedException();
|
||||
|
||||
Writer writer = new Writer(stream);
|
||||
writer.WriteFixedLengthString("slick!\0\0");
|
||||
writer.WriteSingle(1.0f);
|
||||
|
||||
writer.WriteInt32(FileNameSize);
|
||||
|
||||
FileSystemFile[] files = fsom.Items.GetAllFiles();
|
||||
writer.WriteInt32(files.Length);
|
||||
|
||||
int foffset = 20 + ((FileNameSize + 8) * files.Length);
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
writer.WriteFixedLengthString(files[i].Name, FileNameSize);
|
||||
writer.WriteInt32(foffset);
|
||||
|
||||
int datalen = files[i].Source.GetData().Length;
|
||||
writer.WriteInt32(datalen);
|
||||
|
||||
foffset += datalen;
|
||||
}
|
||||
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
writer.WriteBytes(files[i].Source.GetData());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public abstract class DataFormat
|
||||
{
|
||||
protected abstract void LoadInternal(ObjectModel? objectModel, Stream stream);
|
||||
public void Load(ObjectModel? objectModel, Stream stream)
|
||||
{
|
||||
LoadInternal(objectModel, stream);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
|
||||
namespace MBS.Editor.Core.DataFormats.YAML;
|
||||
|
||||
public class YAMLDataFormat : DataFormat
|
||||
{
|
||||
protected override void LoadInternal(ObjectModel? objectModel, Stream stream)
|
||||
{
|
||||
StreamReader sr = new StreamReader(stream);
|
||||
int ic = -1;
|
||||
while ((ic = sr.Read()) != -1)
|
||||
{
|
||||
char c = (char)ic;
|
||||
if (c == '-')
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public class Document
|
||||
{
|
||||
public ObjectModel? ObjectModel { get; set; } = null;
|
||||
public DataFormat? DataFormat { get; set; } = null;
|
||||
public Stream Stream { get; set; }
|
||||
|
||||
public Document(ObjectModel objectModel, DataFormat dataFormat, Stream stream)
|
||||
{
|
||||
ObjectModel = objectModel;
|
||||
DataFormat = dataFormat;
|
||||
Stream = stream;
|
||||
}
|
||||
|
||||
public static Document Load(ObjectModel objectModel, DataFormat dataFormat, Stream stream)
|
||||
{
|
||||
Document d = new Document(objectModel, dataFormat, stream);
|
||||
d.Load();
|
||||
return d;
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
DataFormat.Load(ObjectModel, Stream);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace MBS.Editor.Core;
|
||||
|
||||
public abstract class ObjectModel
|
||||
{
|
||||
|
||||
}
|
||||
@ -19,9 +19,8 @@ public class YamlLibraryPlugin : LibraryPlugin
|
||||
FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
StreamReader sr = new StreamReader(fs);
|
||||
|
||||
var yaml = new YamlStream();
|
||||
yaml.Load(sr);
|
||||
|
||||
// var yaml = new YAMLDataFormat();
|
||||
// yaml.Load(sr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Mocha.Plugins.Libraries.Yaml;
|
||||
|
||||
public class YamlParser
|
||||
{
|
||||
public Dictionary<string, object> Parse(Stream stream)
|
||||
{
|
||||
StreamReader sr = new StreamReader(stream);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user