├── src ├── .idea │ └── .idea.Yarhl │ │ └── .idea │ │ ├── .name │ │ ├── indexLayout.xml │ │ ├── .gitignore │ │ ├── CakeRider.xml │ │ └── vcs.xml ├── nuget.config ├── Yarhl.Examples │ ├── Yarhl.Examples.csproj │ ├── Tutorial │ │ ├── TextEntry.cs │ │ ├── TxtiFormat.cs │ │ ├── Txti2Po.cs │ │ ├── Binary2Txti.cs │ │ └── Program.cs │ ├── Program.cs │ ├── Formats │ │ ├── Converters.cs │ │ └── Formats.cs │ ├── IO │ │ └── DataStreamExamples.cs │ ├── Plugins │ │ └── LocateTypesExamples.cs │ └── Introduction.cs ├── Yarhl │ ├── IO │ │ ├── Serialization │ │ │ ├── ITypeFieldNavigator.cs │ │ │ ├── Attributes │ │ │ │ ├── BinaryOrderAttribute.cs │ │ │ │ ├── BinaryInt24Attribute.cs │ │ │ │ ├── BinaryIgnoreAttribute.cs │ │ │ │ ├── BinaryEndiannessAttribute.cs │ │ │ │ ├── BinaryEnumAttribute.cs │ │ │ │ ├── BinaryBooleanAttribute.cs │ │ │ │ └── BinaryStringAttribute.cs │ │ │ ├── FieldInfo.cs │ │ │ └── DefaultTypePropertyNavigator.cs │ │ ├── EndiannessMode.cs │ │ ├── IBinary.cs │ │ ├── SeekMode.Obsolete4.cs │ │ ├── StreamFormat │ │ │ └── RecyclableMemoryStream.cs │ │ ├── DataStream.Obsolete4.cs │ │ └── NumericExtension.cs │ ├── Yarhl.csproj │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── FileFormat │ │ ├── IFormat.cs │ │ ├── FormatExtensions.cs │ │ ├── IInitializer.Obsolete4.cs │ │ ├── ICloneableFormat.cs │ │ ├── IConverter.cs │ │ ├── ConvertFormat.Obsolete4.cs │ │ └── ConvertFormat.cs │ └── FileSystem │ │ ├── NodeSystem.cs │ │ ├── NavigationMode.cs │ │ ├── NavigableNodeCollection.cs │ │ └── Node.Obsolete4.cs ├── Tests.runsettings ├── Yarhl.sln.DotSettings ├── Yarhl.IntegrationTests │ └── Yarhl.IntegrationTests.csproj ├── Yarhl.Plugins │ ├── Yarhl.Plugins.csproj │ ├── TypeImplementationInfo.cs │ ├── GenericTypeImplementationInfo.cs │ └── FileFormat │ │ └── ConverterTypeInfo.cs ├── Directory.Packages.props ├── Yarhl.PerformanceTests │ ├── Yarhl.PerformanceTests.csproj │ ├── IO │ │ ├── StreamType.cs │ │ ├── DataStreamCompare.cs │ │ └── DataStreamReadWriteTests.cs │ ├── Program.cs │ ├── FileSystem │ │ └── NodeTransformWithInterfaces.cs │ └── Encodings │ │ └── japanese.txt ├── Yarhl.Media.Text │ ├── Yarhl.Media.Text.csproj │ └── Encodings │ │ └── SpanStream.cs ├── Yarhl.UnitTests │ ├── Yarhl.UnitTests.csproj │ ├── FileFormat │ │ ├── TestConvertersDefinition.FormatInheritance.cs │ │ ├── BaseGeneralTests.cs │ │ ├── ConvertFormatTests.FormatInheritance.cs │ │ ├── FormatExtensionsTests.cs │ │ └── ConvertFormatTests.Obsolete4.cs │ ├── Plugins │ │ ├── TestTypesDefinition.cs │ │ └── FileFormat │ │ │ └── TestConvertersDefinition.cs │ ├── IO │ │ ├── FileOpenModeTests.cs │ │ └── NumericExtensionTests.cs │ ├── FileSystem │ │ ├── NavigableNodeCollectionTests.cs │ │ └── NodeTests.Obsolete4.cs │ └── Media │ │ └── Text │ │ └── Encodings │ │ └── SpanStreamTests.cs └── Directory.Build.props ├── docs ├── articles │ ├── media-text │ │ ├── tables.md │ │ ├── encodings.md │ │ ├── po-format.md │ │ └── toc.yml │ ├── core │ │ ├── binary │ │ │ ├── binaryformat.md │ │ │ ├── custom-streams.md │ │ │ ├── binaryreader-writer.md │ │ │ ├── textreader-writer.md │ │ │ ├── attr-serialization.md │ │ │ └── images │ │ │ │ ├── datastream-container.drawio.png │ │ │ │ └── datastream-container-substreams.drawio.png │ │ ├── virtual-file-system │ │ │ ├── container-format.md │ │ │ ├── navigate-nodes.md │ │ │ └── images │ │ │ │ ├── node-simple.drawio.png │ │ │ │ └── node-children.drawio.png │ │ ├── getting-started │ │ │ ├── net-languages.md │ │ │ ├── images │ │ │ │ ├── hex_view.png │ │ │ │ ├── po_poedit.png │ │ │ │ ├── po_vscode.png │ │ │ │ ├── deserializer_output.png │ │ │ │ └── goal_overview.drawio.png │ │ │ ├── resources │ │ │ │ └── texts.bin │ │ │ └── architecture.md │ │ ├── formats │ │ │ ├── cloneable-format.md │ │ │ └── formats.md │ │ └── toc.yml │ ├── changelog.md │ └── plugins │ │ ├── overview.md │ │ ├── locate-types.md │ │ └── load-assembly.md ├── images │ ├── logo.png │ ├── favicon.ico │ ├── logo-50.png │ ├── favicon-128.png │ └── logo-large.png ├── api │ └── .gitignore ├── .gitignore ├── template │ └── public │ │ ├── main.js │ │ └── main.css ├── toc.yml ├── docfx.json └── index.md ├── .prettierrc.yaml ├── GitVersion.yml ├── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── pull_request_template.md └── workflows │ ├── build-and-release.yml │ ├── build.yml │ └── deploy.yml ├── SECURITY.md ├── .vscode ├── settings.json ├── launch.json └── tasks.json ├── .config └── dotnet-tools.json ├── LICENSE ├── GitReleaseManager.yaml ├── CODE_OF_CONDUCT.md └── CONTRIBUTING.md /src/.idea/.idea.Yarhl/.idea/.name: -------------------------------------------------------------------------------- 1 | Yarhl -------------------------------------------------------------------------------- /docs/articles/media-text/tables.md: -------------------------------------------------------------------------------- 1 | # Tables 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/media-text/encodings.md: -------------------------------------------------------------------------------- 1 | # Encodings 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/binary/binaryformat.md: -------------------------------------------------------------------------------- 1 | # Binary format 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/binary/custom-streams.md: -------------------------------------------------------------------------------- 1 | # Custom streams 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/media-text/po-format.md: -------------------------------------------------------------------------------- 1 | # PO translation format 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/binary/binaryreader-writer.md: -------------------------------------------------------------------------------- 1 | # Binary reader and writer 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/binary/textreader-writer.md: -------------------------------------------------------------------------------- 1 | # Text reader and writer 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | overrides: 2 | - files: "*.md" 3 | options: 4 | proseWrap: always 5 | -------------------------------------------------------------------------------- /docs/articles/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | To be filled on preview and stable builds. 4 | -------------------------------------------------------------------------------- /docs/articles/core/virtual-file-system/container-format.md: -------------------------------------------------------------------------------- 1 | # Container format 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/virtual-file-system/navigate-nodes.md: -------------------------------------------------------------------------------- 1 | # Navigate the nodes 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/images/logo.png -------------------------------------------------------------------------------- /docs/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | .manifest 6 | -------------------------------------------------------------------------------- /docs/articles/core/binary/attr-serialization.md: -------------------------------------------------------------------------------- 1 | # (De)serialization via attributes 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/articles/core/getting-started/net-languages.md: -------------------------------------------------------------------------------- 1 | # Yarhl in other .NET languages 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/logo-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/images/logo-50.png -------------------------------------------------------------------------------- /docs/images/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/images/favicon-128.png -------------------------------------------------------------------------------- /docs/images/logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/images/logo-large.png -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | mode: ContinuousDeployment 2 | branches: 3 | develop: 4 | tag: preview 5 | increment: Patch 6 | -------------------------------------------------------------------------------- /docs/articles/core/getting-started/images/hex_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/images/hex_view.png -------------------------------------------------------------------------------- /docs/articles/core/getting-started/resources/texts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/resources/texts.bin -------------------------------------------------------------------------------- /docs/articles/core/getting-started/images/po_poedit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/images/po_poedit.png -------------------------------------------------------------------------------- /docs/articles/core/getting-started/images/po_vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/images/po_vscode.png -------------------------------------------------------------------------------- /docs/articles/core/binary/images/datastream-container.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/binary/images/datastream-container.drawio.png -------------------------------------------------------------------------------- /docs/articles/core/getting-started/images/deserializer_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/images/deserializer_output.png -------------------------------------------------------------------------------- /docs/articles/core/getting-started/images/goal_overview.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/getting-started/images/goal_overview.drawio.png -------------------------------------------------------------------------------- /docs/articles/core/virtual-file-system/images/node-simple.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/virtual-file-system/images/node-simple.drawio.png -------------------------------------------------------------------------------- /docs/articles/core/virtual-file-system/images/node-children.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/virtual-file-system/images/node-children.drawio.png -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | 11 | # DrawIO 12 | .$*.drawio* 13 | -------------------------------------------------------------------------------- /docs/articles/core/binary/images/datastream-container-substreams.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SceneGate/Yarhl/develop/docs/articles/core/binary/images/datastream-container-substreams.drawio.png -------------------------------------------------------------------------------- /docs/articles/media-text/toc.yml: -------------------------------------------------------------------------------- 1 | - name: 📝 Text formats 2 | - name: 🚧 GNU Gettext PO format 3 | href: ./po-format.md 4 | - name: 🚧 Encodings 5 | href: ./encodings.md 6 | - name: 🚧 Tables 7 | href: ./tables.md 8 | -------------------------------------------------------------------------------- /docs/template/public/main.js: -------------------------------------------------------------------------------- 1 | export default { 2 | iconLinks: [ 3 | { 4 | icon: "github", 5 | href: "https://github.com/SceneGate/Yarhl", 6 | title: "GitHub", 7 | }, 8 | ], 9 | }; 10 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | A clear and concise description of what the bug or feature is. 4 | 5 | ### Example 6 | 7 | Small example on how to use the new classes and methods. 8 | 9 | This closes # 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Output 2 | obj/ 3 | bin/ 4 | build/artifacts/ 5 | build/temp/ 6 | /CHANGELOG.md 7 | /CHANGELOG.NEXT.md 8 | 9 | # IDE 10 | *.userprefs 11 | *.user 12 | *.vs 13 | *.DotSettings.user 14 | launchSettings.json 15 | 16 | # Benchmarks 17 | BenchmarkDotNet.Artifacts/ 18 | -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | - name: Core 2 | href: articles/core/ 3 | 4 | - name: Text formats 5 | href: articles/media-text/ 6 | 7 | - name: API 8 | href: api/ 9 | 10 | - name: Changelog 11 | href: articles/changelog.md 12 | 13 | - name: GitHub 14 | href: https://github.com/SceneGate/Yarhl 15 | -------------------------------------------------------------------------------- /docs/articles/core/getting-started/architecture.md: -------------------------------------------------------------------------------- 1 | # Framework architecture 2 | 3 | TODO: base goal and requirements 4 | 5 | ## Reading, deserializing, exporting 6 | 7 | TODO 8 | 9 | ## Core library and plugins 10 | 11 | TODO 12 | 13 | ## Related tools 14 | 15 | TODO 16 | 17 | ## End game 18 | 19 | TODO 20 | -------------------------------------------------------------------------------- /src/.idea/.idea.Yarhl/.idea/indexLayout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ../../yarhl 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/.idea/.idea.Yarhl/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Rider ignored files 5 | /.idea.Yarhl.iml 6 | /projectSettingsUpdater.xml 7 | /modules.xml 8 | /contentModel.xml 9 | # Editor-based HTTP Client requests 10 | /httpRequests/ 11 | # Datasource local storage ignored files 12 | /dataSources/ 13 | /dataSources.local.xml 14 | -------------------------------------------------------------------------------- /src/nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/.idea/.idea.Yarhl/.idea/CakeRider.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 12 | -------------------------------------------------------------------------------- /src/.idea/.idea.Yarhl/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | ## Goal 10 | 11 | TODO: describe with user stories or a short text the goal of the feature. 12 | 13 | ## Description 14 | 15 | TODO: describe the motivation behind of the idea and what it should do. 16 | 17 | ## Proposed solution 18 | 19 | TODO: add any ideas for the implementation or how it should look like. 20 | 21 | ## Acceptance criteria 22 | 23 | TODO: list of expectations it should pass to close the request. 24 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the latest stable version is actively supported with critical bug fixed and 6 | security issues. 7 | 8 | ## Reporting a Vulnerability 9 | 10 | Vulnerabilities can be reported to my personal email address (you can check it 11 | from my [GitHub profile](https://github.com/pleonex)). 12 | 13 | All the security issues will be analyzed and a reply will be given in two 14 | working days. Once the issue is accepted it will be fixed in the current 15 | development branch and for the latest version. A new version would be released. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | ## Description 10 | 11 | TODO: describe the issue 12 | 13 | ## Reproducer 14 | 15 | TODO: steps to reproduce the behavior. 16 | 17 | ## Expected behavior 18 | 19 | TODO: description of the expected behavior. 20 | 21 | ## Report info 22 | 23 | TODO: if applicable, the full exception stacktrace that you get. 24 | 25 | TODO: if applicable, add screenshots to help explain your problem. 26 | 27 | TODO: describe your environment like OS, app/lib version 28 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Yarhl.Examples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | enable 7 | 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | TODO: description of the PR work. 2 | 3 | This PR closes # 4 | 5 | ## Quality check list 6 | 7 | - [ ] Related code has been tested automatically or manually 8 | - [ ] Related documentation is updated 9 | - [ ] I acknowledge I have read and filled this checklist and accept the 10 | [developer certificate of origin](https://developercertificate.org/) 11 | 12 | ## Acceptance criteria 13 | 14 | TODO: list of expectations it has passed from the related issue. 15 | 16 | ## Follow-up work 17 | 18 | TODO: describe any missing or future required work. 19 | 20 | ## Example 21 | 22 | TODO: small code-snippet or screenshot of the work 23 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/ITypeFieldNavigator.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.IO.Serialization; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | 7 | /// 8 | /// Interface to provide implementations that iterate over fields of types. 9 | /// 10 | public interface ITypeFieldNavigator 11 | { 12 | /// 13 | /// Iterate over the fields of a given type using reflection with enumerables. 14 | /// 15 | /// The type to iterate over fields. 16 | /// Enumerable to iterate over its fields. 17 | IEnumerable IterateFields(Type type); 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.rulers": [ 3 | 80, 4 | 120 5 | ], 6 | "editor.renderWhitespace": "boundary", 7 | "editor.defaultFormatter": "esbenp.prettier-vscode", 8 | "[markdown]": { 9 | "editor.formatOnSave": true, 10 | }, 11 | "[csharp]": { 12 | "editor.defaultFormatter": "ms-dotnettools.csharp", 13 | "editor.formatOnType": true 14 | }, 15 | "cSpell.words": [ 16 | "Conv", 17 | "cref", 18 | "Dependee", 19 | "Ekona", 20 | "Diagnoser", 21 | "finalizer", 22 | "msgctxt", 23 | "Msgid", 24 | "typeparam" 25 | ], 26 | "dotnet.defaultSolution": "src/Yarhl.sln", 27 | } -------------------------------------------------------------------------------- /src/Tests.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | cobertura 10 | [.*UnitTest]*,[.*IntegrationTest]* 11 | GeneratedCodeAttribute,ExcludeFromCodeCoverageAttribute,ObsoleteAttribute 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Yarhl.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> 3 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> 4 | True -------------------------------------------------------------------------------- /src/Yarhl.IntegrationTests/Yarhl.IntegrationTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Plugin integration tests for Yarhl. 6 | net6.0;net8.0 7 | 8 | enable 9 | enable 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Yarhl.Plugins/Yarhl.Plugins.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Assembly scaning for file formats and converters implemented with Yarhl. 5 | true 6 | 7 | net6.0;net8.0 8 | 9 | enable 10 | enable 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryOrderAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.IO.Serialization.Attributes; 2 | 3 | using System; 4 | 5 | /// 6 | /// Specify the order to serialize or deserialize the fields in binary format. 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public class BinaryOrderAttribute : Attribute 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | /// The order of the field in the binary serialization. 15 | public BinaryOrderAttribute(int order) 16 | { 17 | Order = order; 18 | } 19 | 20 | /// 21 | /// Gets or sets the order of the field in the binary format. 22 | /// 23 | public int Order { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "gitversion.tool": { 6 | "version": "5.12.0", 7 | "commands": [ 8 | "dotnet-gitversion" 9 | ], 10 | "rollForward": false 11 | }, 12 | "thirdlicense": { 13 | "version": "1.3.1", 14 | "commands": [ 15 | "thirdlicense" 16 | ], 17 | "rollForward": false 18 | }, 19 | "dotnet-reportgenerator-globaltool": { 20 | "version": "5.2.0", 21 | "commands": [ 22 | "reportgenerator" 23 | ], 24 | "rollForward": false 25 | }, 26 | "docfx": { 27 | "version": "2.77.0", 28 | "commands": [ 29 | "docfx" 30 | ], 31 | "rollForward": false 32 | }, 33 | "gitreleasemanager.tool": { 34 | "version": "0.16.0", 35 | "commands": [ 36 | "dotnet-gitreleasemanager" 37 | ], 38 | "rollForward": false 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Run perf test", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "Build release", 12 | "program": "${workspaceFolder}/src/Yarhl.PerformanceTests/bin/Release/net8.0/Yarhl.PerformanceTests.dll", 13 | "args": [ "auto" ], 14 | "cwd": "${workspaceFolder}", 15 | "stopAtEntry": false, 16 | "console": "internalConsole" 17 | }, 18 | { 19 | "name": ".NET Attach", 20 | "type": "coreclr", 21 | "request": "attach", 22 | "processId": "${command:pickProcess}" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /src/Yarhl/Yarhl.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library with features for implementing file formats, converters and a virtual file system. 6 | true 7 | 8 | net6.0;net8.0 9 | 10 | enable 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/Yarhl.PerformanceTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Exe 6 | Performance tests for Yarhl. 7 | net8.0 8 | 9 | false 10 | 11 | 12 | 13 | 14 | Always 15 | 16 | 17 | Always 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Yarhl.Media.Text/Yarhl.Media.Text.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Library with Yarhl converters for text formats. 6 | true 7 | 8 | net6.0;net8.0 9 | 10 | enable 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/Yarhl.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Yarhl unit tests. 6 | net6.0;net8.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/build-and-release.yml: -------------------------------------------------------------------------------- 1 | name: Build and release 2 | 3 | on: 4 | # Dev 5 | workflow_dispatch: 6 | pull_request: 7 | push: 8 | # Preview 9 | branches: [ develop ] 10 | # Stable 11 | tags: [ "v*" ] 12 | 13 | jobs: 14 | build: 15 | name: "Build" 16 | uses: ./.github/workflows/build.yml 17 | with: 18 | dotnet_version: '8.0.401' 19 | 20 | # Preview release on push to main only 21 | # Stable release on version tag push only 22 | deploy: 23 | name: "Deploy" 24 | if: github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags/v') 25 | needs: build 26 | uses: ./.github/workflows/deploy.yml 27 | with: 28 | dotnet_version: '8.0.401' 29 | azure_nuget_feed: 'https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json' 30 | secrets: 31 | nuget_preview_token: "az" # Dummy values as we use Azure DevOps only 32 | nuget_stable_token: ${{ secrets.NUGET_FEED_TOKEN }} 33 | azure_nuget_token: ${{ secrets.ADO_NUGET_FEED_TOKEN }} 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 SceneGate 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/articles/core/formats/cloneable-format.md: -------------------------------------------------------------------------------- 1 | # Cloneable format 2 | 3 | .NET does not provide an interface to guarantee a 4 | [deep clone](https://learn.microsoft.com/en-us/dotnet/api/system.icloneable?view=net-7.0#remarks) 5 | implementation. 6 | 7 | The [`ICloneableFormat`](xref:Yarhl.FileFormat.ICloneableFormat) gives the 8 | possibility to a format implementation to specify how it should _deep_ clone its 9 | data into a new format. This could be as simple as copying its properties into a 10 | new object or in the case of binary data, copying all its bytes into a new 11 | stream. 12 | 13 | [!code-csharp[cloneable](./../../../../src/Yarhl.Examples/Formats/Formats.cs?name=CloneableFormat)] 14 | 15 | The interface already implements `IFormat` so it's not needed to add both. 16 | 17 | > [!IMPORTANT] 18 | > This interface is not required to be implemented by every format but some APIs 19 | > of the library relies on it. For instance it's only possible to clone a 20 | > [node via its constructor]() 21 | > if it has a format that implements 22 | > [`ICloneableFormat`](xref:Yarhl.FileFormat.ICloneableFormat). 23 | 24 | > [!TIP] 25 | > The built-in formats from _Yarhl_ implements 26 | > [`ICloneableFormat`](xref:Yarhl.FileFormat.ICloneableFormat). 27 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/FieldInfo.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.IO.Serialization; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | 7 | /// 8 | /// Information of a field member of a type. 9 | /// 10 | /// Name of the field. 11 | /// Type of the field. 12 | /// Function that returns the fields' value given the object. 13 | /// 14 | /// Function that sets the fields'value on the given object. 15 | /// The first argument is the object and the second the value to set. 16 | /// 17 | /// Optional collection of attributes on the field. 18 | public record FieldInfo( 19 | string Name, 20 | Type Type, 21 | Func GetValueFunc, 22 | Action SetValueFunc, 23 | IEnumerable Attributes) 24 | { 25 | /// 26 | /// Returns the first attribute if any of the given type. 27 | /// 28 | /// The attribute type to search. 29 | /// The attribute on the given type if any or null otherwise. 30 | public T? GetAttribute() 31 | where T : Attribute 32 | { 33 | return Attributes.OfType().FirstOrDefault(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Tutorial/TextEntry.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Tutorial; 21 | 22 | #region Class 23 | public class TextEntry 24 | { 25 | public ushort Id { get; set; } 26 | 27 | public string Text { get; set; } 28 | } 29 | #endregion 30 | -------------------------------------------------------------------------------- /src/Yarhl/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | using System; 21 | using System.Runtime.CompilerServices; 22 | using System.Runtime.InteropServices; 23 | 24 | [assembly: CLSCompliant(true)] 25 | [assembly: ComVisible(true)] 26 | [assembly: InternalsVisibleTo("Yarhl.UnitTests")] 27 | -------------------------------------------------------------------------------- /GitReleaseManager.yaml: -------------------------------------------------------------------------------- 1 | # Configuration values used when creating new releases 2 | create: 3 | include-footer: false 4 | include-sha-section: false 5 | allow-update-to-published: false 6 | 7 | # Configuration values used when exporting release notes 8 | export: 9 | include-created-date-in-title: true 10 | created-date-string-format: MMMM dd, yyyy 11 | perform-regex-removal: false 12 | 13 | # Configuration values used when closing a milestone 14 | close: 15 | use-issue-comments: false 16 | # issue-comment: |- 17 | # :tada: This issue has been resolved in version {milestone} :tada: 18 | # 19 | # The release is available on: 20 | # 21 | # - [GitHub release](https://github.com/{owner}/{repository}/releases/tag/{milestone}) 22 | # 23 | # Your **[GitReleaseManager](https://github.com/GitTools/GitReleaseManager)** bot :package::rocket: 24 | 25 | # The labels that will be used to include issues in release notes. 26 | issue-labels-include: 27 | - Breaking 28 | - Bug 29 | - Duplicate 30 | - Documentation 31 | - Enhancement 32 | - Feature 33 | - Improvement 34 | - Question 35 | 36 | # The labels that will NOT be used when including issues in release notes. 37 | issue-labels-exclude: 38 | - Internal Refactoring 39 | 40 | # Overrides default pluralization and header names for specific labels. 41 | issue-labels-alias: 42 | - name: Documentation 43 | header: Documentation 44 | plural: Documentation 45 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples; 21 | 22 | public static class Program 23 | { 24 | public static void Main(string[] args) 25 | { 26 | // Just used to test from time to time. 27 | Tutorial.Program.FakeMain2(args); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/template/public/main.css: -------------------------------------------------------------------------------- 1 | /* Changing the site font */ 2 | @import url("https://fonts.googleapis.com/css2?family=Nunito:wght@100;400;700&display=swap"); 3 | /* @import url('https://fonts.googleapis.com/css2?family=Inconsolata&display=swap'); */ 4 | @import url("https://fonts.googleapis.com/css2?family=Fira Code&display=swap"); 5 | 6 | /*@import url('https://fonts.cdnfonts.com/css/cascadia-code');*/ 7 | /* @font-face { 8 | font-family: 'Cascadia Code'; 9 | font-style: normal; 10 | font-weight: 100; 11 | src: local('Cascadia Code'), url('https://fonts.cdnfonts.com/s/29131/Cascadia.woff') format('woff'); 12 | } */ 13 | 14 | :root { 15 | --bs-font-sans-serif: "Nunito"; 16 | --bs-font-monospace: "Fira Code"; 17 | } 18 | 19 | /* Hide breadcrum bar on large screen as it only links to itself */ 20 | @media (min-width: 768px) { 21 | .actionbar { 22 | display: none !important; 23 | } 24 | } 25 | 26 | /* Give more space for section separation in a doc */ 27 | h2 { 28 | margin-top: 2rem !important; 29 | } 30 | 31 | /* Improve TOC with a line for categories (entries without link) */ 32 | .toc span.name-only { 33 | border-bottom-color: var(--bs-tertiary-color) !important; 34 | border-bottom-width: 2px !important; 35 | border-bottom-style: solid !important; 36 | margin-bottom: 0 !important; 37 | margin-top: 0.6rem !important; 38 | } 39 | 40 | .toc span.name-only:first() { 41 | margin-top: 0.4rem !important; 42 | } 43 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Tutorial/TxtiFormat.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Tutorial; 21 | 22 | #region Class 23 | using System.Collections.ObjectModel; 24 | using Yarhl.FileFormat; 25 | 26 | public class TxtiFormat : IFormat 27 | { 28 | public Collection Entries { get; init; } = new(); 29 | } 30 | #endregion 31 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "process", 6 | "command": "dotnet", 7 | "args": [ 8 | "run", 9 | "--project", 10 | "build/orchestrator/", 11 | ], 12 | "group": { 13 | "kind": "build", 14 | "isDefault": true 15 | }, 16 | "problemMatcher": ["$msCompile"], 17 | "label": "Build" 18 | }, 19 | { 20 | "type": "process", 21 | "command": "dotnet", 22 | "args": [ 23 | "run", 24 | "--project", 25 | "build/orchestrator/", 26 | "--", 27 | "--dotnet-configuration=Release" 28 | ], 29 | "group": { 30 | "kind": "build", 31 | }, 32 | "problemMatcher": ["$msCompile"], 33 | "label": "Build release" 34 | }, 35 | { 36 | "type": "process", 37 | "command": "dotnet", 38 | "args": [ 39 | "run", 40 | "--project", 41 | "build/orchestrator/", 42 | "--", 43 | "--target=Bundle" 44 | ], 45 | "group": { 46 | "kind": "build", 47 | }, 48 | "problemMatcher": ["$msCompile"], 49 | "label": "Bundle" 50 | }, 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /docs/articles/plugins/overview.md: -------------------------------------------------------------------------------- 1 | # Plugins overview 2 | 3 | `Yarhl.Plugins` provides a set of APIs that helps to load .NET assemblies and 4 | find types. 5 | 6 | Its main goal is to find [converter](../core/formats/converters.md) and 7 | [format](../core/formats/formats.md) types in external .NET assemblies. Generic 8 | applications, like [SceneGate](https://github.com/SceneGate/SceneGate), that 9 | have no knowledge in the converters to use, could use the APIs to find and 10 | propose them to the user. 11 | 12 | The _plugins_ are regular .NET libraries or executable that contains 13 | implementations of _converters_ and _formats_. They don't need to implement any 14 | additional interface or fullfil other requirements. 15 | 16 | The main APIs are: 17 | 18 | - [`AssemblyLoadContextExtensions`](./load-assembly.md): extension methods for 19 | `AssemblyLoadContext` to load .NET assemblies from disk. 20 | - [`TypeLocator`](./locate-types.md#typelocator): find types that implement a 21 | specific interface. 22 | - [`ConverterLocator`](./locate-types.md#converterlocator): find _converter_ and 23 | _format_ types. 24 | 25 | ```mermaid 26 | flowchart TB 27 | Application ---> |Load external .NET assemblies| AssemblyLoadContext 28 | Application --> |Find converters| ConverterLocator 29 | ConverterLocator --> |Find implementations\nof IConverter<,>| TypeLocator 30 | TypeLocator --> |Iterate through types in\nloaded assemblies| AssemblyLoadContext 31 | ``` 32 | 33 | You can get more information in their subpage. 34 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryInt24Attribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Property is an Int24 value. 26 | /// 27 | [AttributeUsage(AttributeTargets.Property)] 28 | public sealed class BinaryInt24Attribute : Attribute 29 | { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryIgnoreAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Set to ignore the property when serializing. 26 | /// 27 | [AttributeUsage(AttributeTargets.Property)] 28 | public sealed class BinaryIgnoreAttribute : Attribute 29 | { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Yarhl.Plugins/TypeImplementationInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Plugins; 21 | 22 | /// 23 | /// Provides information about a type that implements a base type. 24 | /// 25 | /// The name of the implementation type. Shortcut for Type.FullName. 26 | /// The implementation type. 27 | public record TypeImplementationInfo(string Name, Type Type); 28 | -------------------------------------------------------------------------------- /src/Yarhl/IO/EndiannessMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO 21 | { 22 | /// 23 | /// Endianness mode. 24 | /// 25 | public enum EndiannessMode 26 | { 27 | /// 28 | /// Little endian. 29 | /// 30 | LittleEndian, 31 | 32 | /// 33 | /// Big endian. 34 | /// 35 | BigEndian, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileFormat/TestConvertersDefinition.FormatInheritance.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.FileFormat; 2 | 3 | using Yarhl.FileFormat; 4 | 5 | #pragma warning disable SA1649 // File name match type name 6 | 7 | public interface IInterface 8 | { 9 | int Z { get; } 10 | } 11 | 12 | public class InterfaceImpl : IInterface 13 | { 14 | public int Z { get; set; } 15 | } 16 | 17 | public class ConverterInterface : 18 | IConverter 19 | { 20 | public int Convert(IInterface source) 21 | { 22 | return source.Z; 23 | } 24 | } 25 | 26 | public class BaseFormat 27 | { 28 | public ushort X { get; set; } 29 | } 30 | 31 | public class DerivedFormat : BaseFormat 32 | { 33 | public ushort Y { get; set; } 34 | } 35 | 36 | public class ConvertDerivedFormat : 37 | IConverter, IConverter 38 | { 39 | public DerivedFormat Convert(ushort source) 40 | { 41 | return new DerivedFormat { 42 | X = source, 43 | Y = (ushort)(source + 1), 44 | }; 45 | } 46 | 47 | public ushort Convert(DerivedFormat source) 48 | { 49 | return source.Y; 50 | } 51 | } 52 | 53 | public class ConvertBaseFormat : 54 | IConverter, IConverter 55 | { 56 | public BaseFormat Convert(int source) 57 | { 58 | return new BaseFormat { 59 | X = (ushort)(source + 2), 60 | }; 61 | } 62 | 63 | public int Convert(BaseFormat source) 64 | { 65 | return source.X + 5; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Yarhl/IO/IBinary.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO 21 | { 22 | using Yarhl.FileFormat; 23 | 24 | /// 25 | /// Binary format. 26 | /// 27 | public interface IBinary : IFormat 28 | { 29 | /// 30 | /// Gets the stream. 31 | /// 32 | /// The stream. 33 | DataStream Stream { 34 | get; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/IFormat.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat 21 | { 22 | /// 23 | /// File format marker. 24 | /// 25 | [System.Diagnostics.CodeAnalysis.SuppressMessage( 26 | "Microsoft.Design", 27 | "CA1040:AvoidEmptyInterfaces", 28 | Justification = "Provides type discovery while scanning assemblies and extension methods.")] 29 | public interface IFormat 30 | { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Yarhl/FileSystem/NodeSystem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileSystem 21 | { 22 | /// 23 | /// Basic settings and configurations for a system of nodes. 24 | /// 25 | public static class NodeSystem 26 | { 27 | /// 28 | /// Gets the path separator. 29 | /// 30 | /// The path separator. 31 | public static string PathSeparator { 32 | get { return "/"; } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/FormatExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.FileFormat; 2 | 3 | using System; 4 | 5 | /// 6 | /// Extensions that applies to every format. 7 | /// 8 | public static class FormatExtensions 9 | { 10 | /// 11 | /// Converts the format using a converter with the specified type. 12 | /// 13 | /// Source format. 14 | /// Destination format. 15 | /// The input object to convert. 16 | /// The converter to use. 17 | /// 18 | /// Value indicating whether it disposes the source input after converting. 19 | /// 20 | /// 21 | /// Value indicating whether it disposes the converter after using it. 22 | /// 23 | /// The output from the converter. 24 | public static TDst ConvertWith( 25 | this TSrc src, 26 | IConverter converter, 27 | bool disposeInput = false, 28 | bool disposeConverter = false) 29 | where TSrc : IFormat 30 | { 31 | // It looks useless but allows a cleaner fluent-like API: 32 | // format.ConvertWith(converter1).ConvertWith(converter2) 33 | TDst result = converter.Convert(src); 34 | 35 | if (disposeInput && src is IDisposable disposeSrc) { 36 | disposeSrc.Dispose(); 37 | } 38 | 39 | if (disposeConverter && converter is IDisposable disposeConv) { 40 | disposeConv.Dispose(); 41 | } 42 | 43 | return result; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Yarhl/FileSystem/NavigationMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileSystem 21 | { 22 | /// 23 | /// Navigation mode through a file system. 24 | /// 25 | public enum NavigationMode 26 | { 27 | /// 28 | /// Breadth-First Search. 29 | /// Returns first nodes in the same directory. 30 | /// 31 | BreadthFirst, 32 | 33 | /// 34 | /// Depth-First Search. 35 | /// Return first nodes in sub-directories. 36 | /// 37 | DepthFirst, 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/articles/core/toc.yml: -------------------------------------------------------------------------------- 1 | - name: ✨ Getting started 2 | - name: Introduction 3 | href: ../../index.md 4 | - name: Getting started guide 5 | href: ./getting-started/tutorial.md 6 | - name: 🚧 Framework architecture 7 | href: ./getting-started/architecture.md 8 | - name: 🚧 Yarhl in other .NET languages 9 | href: ./getting-started/net-languages.md 10 | 11 | - name: ♻ Formats and converters 12 | - name: Formats 13 | href: ./formats/formats.md 14 | - name: Converters 15 | href: ./formats/converters.md 16 | - name: Advanced 17 | items: 18 | - name: Cloneable format 19 | href: ./formats/cloneable-format.md 20 | - name: Use cases for converters 21 | href: ./formats/converters-usecases.md 22 | 23 | - name: 📁 Virtual file system 24 | - name: Nodes 25 | href: ./virtual-file-system/nodes.md 26 | - name: Node factory 27 | href: ./virtual-file-system/node-factory.md 28 | - name: 🚧 Node navigation 29 | href: ./virtual-file-system/navigate-nodes.md 30 | - name: 🚧 Container format 31 | href: ./virtual-file-system/container-format.md 32 | 33 | - name: 🧮 Binary formats 34 | - name: DataStream 35 | href: ./binary/datastream.md 36 | - name: 🚧 Binary format 37 | href: ./binary/binaryformat.md 38 | - name: 🚧 Binary reader and writer 39 | href: ./binary/binaryreader-writer.md 40 | - name: 🚧 Text reader and writer 41 | href: ./binary/textreader-writer.md 42 | - name: 🚧 (De)serialization via attributes 43 | href: ./binary/attr-serialization.md 44 | - name: 🚧 Custom streams 45 | href: ./binary/custom-streams.md 46 | 47 | - name: 🔌 Plugins 48 | - name: Overview 49 | href: ../plugins/overview.md 50 | - name: Loading assemblies 51 | href: ../plugins/load-assembly.md 52 | - name: Find converters 53 | href: ../plugins/locate-types.md 54 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/IO/StreamType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.PerformanceTests.IO 21 | { 22 | /// 23 | /// The type of stream to test. 24 | /// 25 | public enum StreamType 26 | { 27 | /// 28 | /// A stream in memory (array). 29 | /// 30 | MemoryStream, 31 | 32 | /// 33 | /// A recyclable stream object. 34 | /// 35 | RecyclableStream, 36 | 37 | /// 38 | /// A stream from a file. 39 | /// 40 | FileStream, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Tutorial/Txti2Po.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Tutorial; 21 | 22 | #region Converter 23 | using Yarhl.FileFormat; 24 | using Yarhl.Media.Text; 25 | 26 | public class Txti2Po : IConverter 27 | { 28 | public Po Convert(TxtiFormat source) 29 | { 30 | var metadata = new PoHeader("MyProject", "me@example.com", "en"); 31 | var po = new Po(metadata); 32 | 33 | foreach (var entry in source.Entries) { 34 | var poEntry = new PoEntry(entry.Text); 35 | poEntry.Context = $"ID: 0x{entry.Id:X2}"; 36 | 37 | po.Add(poEntry); 38 | } 39 | 40 | return po; 41 | } 42 | } 43 | #endregion 44 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/IInitializer.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat 21 | { 22 | using System; 23 | 24 | /// 25 | /// Initialization interface. 26 | /// 27 | /// Type of the parameters for the initialize. 28 | [Obsolete("IInitialize is obsolete. Use the converter constructor or properties")] 29 | public interface IInitializer 30 | { 31 | /// 32 | /// Initialize the instance with the specified parameters. 33 | /// 34 | /// Parameters for the initialize. 35 | void Initialize(T parameters); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Yarhl/IO/SeekMode.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO 21 | { 22 | using System; 23 | 24 | /// 25 | /// Seek mode for DataStream. 26 | /// 27 | [Obsolete("Use overloads with System.IO.SeekOrigin")] 28 | public enum SeekMode 29 | { 30 | /// 31 | /// Position from the origin of the DataStream. 32 | /// 33 | Start, 34 | 35 | /// 36 | /// Position from the current position. 37 | /// 38 | Current, 39 | 40 | /// 41 | /// Position going back from the end of the DataStream. 42 | /// 43 | End, 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/ICloneableFormat.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat 21 | { 22 | /// 23 | /// Cloneable format interface. 24 | /// 25 | public interface ICloneableFormat : IFormat 26 | { 27 | /// 28 | /// Deep clones a format into a new object. 29 | /// 30 | /// The cloned format. 31 | /// 32 | /// A 'deep copy' must create the necessary copies, in the way that 33 | /// any change in the original node (or any of it's member hierarchy) won't affect 34 | /// the cloned node. 35 | /// 36 | object DeepClone(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Yarhl.Plugins/GenericTypeImplementationInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Plugins; 21 | 22 | /// 23 | /// Provides information about a type that implements a generic base type. 24 | /// 25 | /// The name of the implementation type. Shortcut for Type.FullName. 26 | /// The implementation type. 27 | /// The actual generic base type with type parameters implemented. 28 | /// 29 | /// The collection of the type parameters in the generic base type implemented. 30 | /// 31 | public record GenericTypeImplementationInfo( 32 | string Name, 33 | Type Type, 34 | Type GenericBaseType, 35 | IReadOnlyList GenericTypeParameters) 36 | : TypeImplementationInfo(Name, Type); 37 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | dotnet_version: 7 | required: true 8 | type: string 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | matrix: 14 | os: [ ubuntu-latest, macos-latest, windows-latest ] 15 | include: 16 | # By default they are no "main build" but if it matches "os" then yes. 17 | - os: ubuntu-latest 18 | is_main_build: true 19 | name: "${{ matrix.os }}" 20 | runs-on: ${{ matrix.os }} 21 | steps: 22 | - name: "Checkout" 23 | uses: actions/checkout@v4 24 | with: 25 | fetch-depth: 0 # We need full history for version number 26 | 27 | - name: "Setup .NET SDK" 28 | uses: actions/setup-dotnet@v4 29 | with: 30 | dotnet-version: ${{ inputs.dotnet_version }} 31 | 32 | - name: "Setup .NET 6.0 SDK" 33 | uses: actions/setup-dotnet@v4 34 | with: 35 | dotnet-version: '6.0.424' 36 | 37 | - name: "Build and test" 38 | run: dotnet run --project build/orchestrator -- --target=Default --dotnet-configuration=Release 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | 42 | - name: "Bundle" 43 | if: ${{ matrix.is_main_build }} 44 | run: dotnet run --project build/orchestrator -- --target=Bundle --dotnet-configuration=Release 45 | env: 46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 47 | 48 | - name: "Publish artifacts to CI" 49 | if: ${{ matrix.is_main_build }} 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: "Artifacts" 53 | retention-days: 7 54 | path: | 55 | build/artifacts/ 56 | !build/artifacts/docs 57 | 58 | - name: Publish docs artifact to CI 59 | if: ${{ matrix.is_main_build }} 60 | uses: actions/upload-pages-artifact@v3 61 | with: 62 | path: build/artifacts/docs 63 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Formats/Converters.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Formats; 21 | 22 | using Yarhl.Media.Text; 23 | 24 | public class Converters 25 | { 26 | public void SerializePo() 27 | { 28 | #region SerializePo 29 | // Create a test PO model format to convert. 30 | var poFormat = new Po(new PoHeader("software", "SceneGate", "en-US")); 31 | poFormat.Add(new PoEntry("Hello, world!")); 32 | 33 | // Create a new converter instance 34 | var po2binary = new Po2Binary(); 35 | 36 | // Convert! 37 | using var binaryPoFormat = po2binary.Convert(poFormat); 38 | 39 | // Binary format is a wrapper over a DataStream (enhanced System.IO.Stream) 40 | // We can now save the Stream into a file 41 | binaryPoFormat.Stream.WriteTo("strings.po"); 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "Yarhl/*.csproj", 8 | "Yarhl.Media.Text/*.csproj", 9 | "Yarhl.Plugins/*.csproj", 10 | ], 11 | "src": "../src" 12 | } 13 | ], 14 | "dest": "api", 15 | "includePrivateMembers": false, 16 | "disableGitFeatures": false, 17 | "disableDefaultFilter": false, 18 | "noRestore": false, 19 | "namespaceLayout": "nested", 20 | "memberLayout": "samePage", 21 | "EnumSortOrder": "alphabetic", 22 | "allowCompilationErrors": false 23 | } 24 | ], 25 | "build": { 26 | "content": [ 27 | { 28 | "files": [ 29 | "api/**.yml", 30 | "api/index.md" // TODO: homepage with namespace overview 31 | ] 32 | }, 33 | { "files": "**/*.{md,yml}", "src": "articles", "dest": "docs" }, 34 | { "files": [ "toc.yml", "*.md" ] } 35 | ], 36 | "resource": [ 37 | { 38 | "files": [ "**/images/**", "**/resources/**" ], 39 | "exclude": [ "_site/**", "obj/**" ] 40 | } 41 | ], 42 | "output": "_site", 43 | "globalMetadata": { 44 | "_appTitle": "Yarhl", 45 | "_appName": "Yarhl", 46 | "_appFooter": "Part of the SceneGate framework. Docs made with docfx", 47 | "_appLogoPath": "images/logo-50.png", 48 | "_appFaviconPath": "images/favicon.ico", 49 | "_enableSearch": true, 50 | "_enableNewTab": true, 51 | "_lang": "en" 52 | }, 53 | "fileMetadataFiles": [], 54 | "template": [ 55 | "default", 56 | "modern", 57 | "template" 58 | ], 59 | "postProcessors": [], 60 | "keepFileLink": false, 61 | "disableGitFeatures": false, 62 | "sitemap": { 63 | "baseUrl": "https://scenegate.github.io/Yarhl", 64 | "priority": 0.5, 65 | "changefreq": "monthly" 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryEndiannessAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Specify the endianness to serialize or deserialize a field. 26 | /// 27 | [AttributeUsage(AttributeTargets.Property)] 28 | public sealed class BinaryEndiannessAttribute : Attribute 29 | { 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | /// Endianness mode for the property. 34 | public BinaryEndiannessAttribute(EndiannessMode mode) 35 | { 36 | Mode = mode; 37 | } 38 | 39 | /// 40 | /// Gets the endianness mode. 41 | /// 42 | public EndiannessMode Mode { 43 | get; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/IO/DataStreamExamples.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.IO; 21 | 22 | using Yarhl.IO; 23 | 24 | public static class DataStreamExamples 25 | { 26 | public static void CreateSubStreamConstructor() 27 | { 28 | #region SubStreamConstructor 29 | var baseStream = new FileStream("container.bin", FileMode.Open); 30 | using var file1Stream = new DataStream(baseStream, 0x100, 0x2C0); 31 | using var file2Stream = new DataStream(baseStream, 0x3C0, 0x80); 32 | #endregion 33 | } 34 | 35 | public static void CreateSubStreamSlice() 36 | { 37 | #region SubStreamSlice 38 | DataStream containerStream = DataStreamFactory.FromFile("container.bin", FileOpenMode.Read); 39 | using DataStream file1Stream = containerStream.Slice(0x100, 0x2C0); 40 | using DataStream file2Stream = containerStream.Slice(0x3C0, 0x80); 41 | using DataStream lastFileStream = containerStream.Slice(0x8400); 42 | #endregion 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/IConverter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat 21 | { 22 | /// 23 | /// Non-generic converter interface. 24 | /// 25 | [System.Diagnostics.CodeAnalysis.SuppressMessage( 26 | "Microsoft.Design", 27 | "CA1040:AvoidEmptyInterfaces", 28 | Justification = "Provides a minimal of type checking when we don't know the generics")] 29 | public interface IConverter 30 | { 31 | } 32 | 33 | /// 34 | /// Format converter interface. 35 | /// 36 | /// Source format. 37 | /// Destination format. 38 | public interface IConverter : IConverter 39 | { 40 | /// 41 | /// Converts the specified source into the given type. 42 | /// 43 | /// The converted source. 44 | /// Source format to convert. 45 | TDst Convert(TSrc source); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/IO/DataStreamCompare.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.PerformanceTests.IO 21 | { 22 | using BenchmarkDotNet.Attributes; 23 | using Yarhl.IO; 24 | 25 | public class DataStreamCompare 26 | { 27 | DataStream stream1; 28 | DataStream stream2; 29 | 30 | [Params(32, 1024, 5 * 1024, 80 * 1024, 1024 * 1024)] 31 | public long Length { get; set; } 32 | 33 | [GlobalSetup] 34 | public void SetUp() 35 | { 36 | stream1 = new DataStream(); 37 | for (int i = 0; i < Length; i++) { 38 | stream1.WriteByte((byte)(i % 256)); 39 | } 40 | 41 | stream2 = new DataStream(); 42 | stream1.WriteTo(stream2); 43 | } 44 | 45 | [GlobalCleanup] 46 | public void CleanUp() 47 | { 48 | stream1?.Dispose(); 49 | stream2?.Dispose(); 50 | } 51 | 52 | [Benchmark] 53 | public void Compare() 54 | { 55 | stream1.Compare(stream2); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Tutorial/Binary2Txti.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Tutorial; 21 | 22 | #region Class 23 | using System.Text; 24 | using Yarhl.FileFormat; 25 | using Yarhl.IO; 26 | 27 | public class Binary2Txti : IConverter 28 | { 29 | #endregion 30 | 31 | #region ValidateHeader 32 | public TxtiFormat Convert(IBinary source) 33 | { 34 | var reader = new DataReader(source.Stream); 35 | 36 | if (reader.ReadString(bytesCount: 4) != "TXTI") { 37 | throw new FormatException("Invalid format"); 38 | } 39 | #endregion 40 | 41 | #region ReadEntries 42 | var txtiFormat = new TxtiFormat(); 43 | 44 | int numEntries = reader.ReadInt32(); 45 | for (int i = 0; i < numEntries; i++) { 46 | var entry = new TextEntry(); 47 | entry.Id = reader.ReadUInt16(); 48 | entry.Text = reader.ReadString(Encoding.Unicode); 49 | 50 | txtiFormat.Entries.Add(entry); 51 | } 52 | 53 | return txtiFormat; 54 | #endregion 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileFormat/BaseGeneralTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.FileFormat 21 | { 22 | using System.Linq; 23 | using NUnit.Framework; 24 | using Yarhl.FileFormat; 25 | using Yarhl.Plugins.FileFormat; 26 | 27 | public abstract class BaseGeneralTests 28 | where T : IFormat 29 | { 30 | protected string Name => typeof(T).FullName; 31 | 32 | [Test] 33 | public void FormatIsFoundAndIsUnique() 34 | { 35 | var formats = ConverterLocator.Default.Formats 36 | .Select(f => f.Type); 37 | Assert.That(formats, Does.Contain(typeof(T))); 38 | Assert.That(formats, Is.Unique); 39 | } 40 | 41 | [Test] 42 | public void FormatNameMatchAndIsUnique() 43 | { 44 | var names = ConverterLocator.Default.Formats 45 | .Select(f => f.Name); 46 | Assert.That(names, Does.Contain(Name)); 47 | Assert.That(names, Is.Unique); 48 | } 49 | 50 | protected abstract T CreateDummyFormat(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryEnumAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Define how to read and write a Enum value. 26 | /// Default type is defined in the enum type 27 | /// 28 | [AttributeUsage(AttributeTargets.Property)] 29 | public sealed class BinaryEnumAttribute : Attribute 30 | { 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// 34 | public BinaryEnumAttribute() 35 | { 36 | UnderlyingType = null; 37 | } 38 | 39 | /// 40 | /// Gets or sets the underlying type to use to serialize and deserialize. 41 | /// 42 | /// 43 | /// If set to null (default), it will use the defined underlying type 44 | /// in the enumaration type. 45 | /// 46 | public Type? UnderlyingType { 47 | get; 48 | set; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Formats/Formats.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Formats; 21 | 22 | using System.Collections.ObjectModel; 23 | using Yarhl.FileFormat; 24 | 25 | public static class Formats 26 | { 27 | #region FormatImpl 28 | public class GameTextFormat : IFormat 29 | { 30 | public Collection Texts { get; init; } 31 | 32 | public int SceneId { get; set; } 33 | } 34 | #endregion 35 | 36 | #region FormatWrapper 37 | public class SoundFormat : ThirdPartyWave, IFormat 38 | { 39 | } 40 | #endregion 41 | 42 | public class ThirdPartyWave 43 | { 44 | } 45 | 46 | #region CloneableFormat 47 | public class Image : ICloneableFormat 48 | { 49 | public int Width { get; set; } 50 | 51 | public int Height { get; set; } 52 | 53 | public byte[] IndexedPixels { get; set; } 54 | 55 | public object DeepClone() 56 | { 57 | return new Image { 58 | Width = Width, 59 | Height = Height, 60 | IndexedPixels = IndexedPixels.ToArray(), 61 | }; 62 | } 63 | } 64 | #endregion 65 | } 66 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/DefaultTypePropertyNavigator.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.IO.Serialization; 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using Yarhl.IO.Serialization.Attributes; 8 | 9 | /// 10 | /// Field navigator for types that iterate over public non-static properties only. 11 | /// It includes inherited properties. It follows the order given by the order attribute. 12 | /// 13 | public class DefaultTypePropertyNavigator : ITypeFieldNavigator 14 | { 15 | /// 16 | public virtual IEnumerable IterateFields(Type type) 17 | { 18 | PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) 19 | .Where(p => p.CanRead && (p.GetGetMethod(false)?.IsPublic ?? false)) 20 | .Where(p => p.CanWrite && (p.GetSetMethod(false)?.IsPublic ?? false)) 21 | .Where(p => p.GetCustomAttribute() is null) 22 | .ToArray(); 23 | 24 | SortProperties(properties); 25 | 26 | foreach (PropertyInfo property in properties) { 27 | var info = new FieldInfo( 28 | property.Name, 29 | property.PropertyType, 30 | property.GetValue, 31 | property.SetValue, 32 | property.GetCustomAttributes()); 33 | 34 | yield return info; 35 | } 36 | } 37 | 38 | private static void SortProperties(PropertyInfo[] properties) 39 | { 40 | int[] orderKeys = properties 41 | .Select(p => p.GetCustomAttribute()) 42 | .Where(p => p is not null) 43 | .Select(p => p!.Order) 44 | .ToArray(); 45 | 46 | #if NET6_0 47 | if (orderKeys.Length != properties.Length) { 48 | throw new FormatException("Prior .NET 8.0, every property must have the BinaryFieldOrder attribute"); 49 | } 50 | 51 | Array.Sort(orderKeys, properties); 52 | #elif NET8_0_OR_GREATER 53 | if (orderKeys.Length > 0 && orderKeys.Length != properties.Length) { 54 | throw new FormatException("BinaryFieldOrder must be applied to none or all properties"); 55 | } 56 | 57 | if (orderKeys.Length > 0) { 58 | Array.Sort(orderKeys, properties); 59 | } 60 | #endif 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Yarhl/FileSystem/NavigableNodeCollection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileSystem 21 | { 22 | using System.Collections.Generic; 23 | using System.Collections.ObjectModel; 24 | using System.Linq; 25 | 26 | /// 27 | /// Read-only collection of NavigableNodes. 28 | /// 29 | /// The implementation of NavigableNodes. 30 | public class NavigableNodeCollection : ReadOnlyCollection 31 | where T : NavigableNode 32 | { 33 | /// 34 | /// Initializes a new instance of the 35 | /// class. 36 | /// 37 | /// Original list of nodes. 38 | public NavigableNodeCollection(IList list) 39 | : base(list) 40 | { 41 | } 42 | 43 | /// 44 | /// Gets the 45 | /// with the specified name. 46 | /// 47 | /// Node name. 48 | /// The node with the same name or null if not found. 49 | public T? this[string name] => this.FirstOrDefault(node => node?.Name == name); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: "Deploy" 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | dotnet_version: 7 | required: true 8 | type: string 9 | azure_nuget_feed: 10 | required: false 11 | type: string 12 | secrets: 13 | nuget_preview_token: 14 | required: false 15 | nuget_stable_token: 16 | required: false 17 | azure_nuget_token: 18 | required: false 19 | 20 | jobs: 21 | upload_doc: 22 | name: "Documentation" 23 | runs-on: "ubuntu-latest" 24 | # Grant GITHUB_TOKEN the permissions required to make a Pages deployment 25 | permissions: 26 | pages: write # to deploy to Pages 27 | id-token: write # to verify the deployment originates from an appropriate source 28 | # Deploy to the github-pages environment 29 | environment: 30 | name: github-pages 31 | url: ${{ steps.deployment.outputs.page_url }} 32 | steps: 33 | - name: Deploy to GitHub Pages 34 | id: deployment 35 | uses: actions/deploy-pages@v4 36 | 37 | push_artifacts: 38 | name: "Artifacts" 39 | runs-on: "ubuntu-latest" 40 | steps: 41 | - name: "Checkout" 42 | uses: actions/checkout@v4 43 | with: 44 | fetch-depth: 0 # We need full history for version number 45 | 46 | - name: "Download artifacts" 47 | uses: actions/download-artifact@v4 48 | with: 49 | name: "Artifacts" 50 | path: "./build/artifacts/" 51 | 52 | - name: "Setup .NET SDK" 53 | uses: actions/setup-dotnet@v4 54 | with: 55 | dotnet-version: ${{ inputs.dotnet_version }} 56 | 57 | # Weird way to authenticate in Azure DevOps Artifacts 58 | # Then, we need to setup VSS_NUGET_EXTERNAL_FEED_ENDPOINTS 59 | - name: "Install Azure Artifacts Credential Provider" 60 | run: wget -qO- https://aka.ms/install-artifacts-credprovider.sh | bash 61 | 62 | - name: "Deploy artifacts" 63 | run: dotnet run --project build/orchestrator -- --target=Deploy 64 | env: 65 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 66 | STABLE_NUGET_FEED_TOKEN: ${{ secrets.nuget_stable_token }} 67 | PREVIEW_NUGET_FEED_TOKEN: ${{ secrets.nuget_preview_token }} 68 | VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: '{"endpointCredentials": [{"endpoint":"${{ inputs.azure_nuget_feed }}", "username":"", "password":"${{ secrets.azure_nuget_token }}"}]}' 69 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/Plugins/TestTypesDefinition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.Plugins; 21 | 22 | using System; 23 | 24 | #pragma warning disable SA1649 // File name should match first type name 25 | #pragma warning disable S2326 // Unused type parameters should be removed 26 | 27 | public interface IExistsInterface 28 | { 29 | } 30 | 31 | public interface IGenericInterface 32 | { 33 | } 34 | 35 | public interface IGenericInterface 36 | { 37 | } 38 | 39 | public class ExistsClass : IExistsInterface 40 | { 41 | } 42 | 43 | public class Generic1Class : IGenericInterface 44 | { 45 | } 46 | 47 | public class Generic2Class : IGenericInterface 48 | { 49 | } 50 | 51 | public class GenericMultipleClass : 52 | IGenericInterface, 53 | IGenericInterface 54 | { 55 | } 56 | 57 | public interface ISecondInterface : IExistsInterface 58 | { 59 | } 60 | 61 | public abstract class AbstractClass : IExistsInterface 62 | { 63 | } 64 | 65 | public interface ISecondGenericInterface : IGenericInterface 66 | { 67 | } 68 | 69 | public abstract class AbstractGenericClass : IGenericInterface 70 | { 71 | } 72 | 73 | public class ConstructorWithException 74 | { 75 | public ConstructorWithException() 76 | { 77 | throw new Exception(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | using System.CommandLine; 21 | using BenchmarkDotNet.Running; 22 | 23 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("", "SA1516", Justification = "Broken blank line rule")] 24 | 25 | var encodingPerf = new Command("encoding", "Run the perf test for encodings"); 26 | encodingPerf.SetHandler(() => BenchmarkRunner.Run()); 27 | 28 | var streamComparePerf = new Command("stream-compare", "Run the perf test for DataStream compare"); 29 | streamComparePerf.SetHandler(() => BenchmarkRunner.Run()); 30 | 31 | var streamReadWritePerf = new Command("stream-rw", "Run the perf test for DataStream Read/Write"); 32 | streamReadWritePerf.SetHandler(() => BenchmarkRunner.Run()); 33 | 34 | var nodeTransformInterfaces = new Command("node-transformWithInterfaces", "Run the perf test for Node.TransformWith"); 35 | nodeTransformInterfaces.SetHandler(() => BenchmarkRunner.Run()); 36 | 37 | var rootCommand = new RootCommand("Yarhl performance tests") 38 | { 39 | encodingPerf, 40 | streamComparePerf, 41 | streamReadWritePerf, 42 | nodeTransformInterfaces, 43 | }; 44 | 45 | return rootCommand.Invoke(args); 46 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/IO/FileOpenModeTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.IO 21 | { 22 | using System; 23 | using System.IO; 24 | using NUnit.Framework; 25 | using Yarhl.IO; 26 | 27 | [TestFixture] 28 | public class FileOpenModeTests 29 | { 30 | [Test] 31 | public void ConvertToFileMode() 32 | { 33 | Assert.AreEqual(FileMode.Open, FileOpenMode.Read.ToFileMode()); 34 | Assert.AreEqual(FileMode.Create, FileOpenMode.Write.ToFileMode()); 35 | Assert.AreEqual(FileMode.Append, FileOpenMode.Append.ToFileMode()); 36 | Assert.AreEqual(FileMode.OpenOrCreate, FileOpenMode.ReadWrite.ToFileMode()); 37 | Assert.Throws(() => ((FileOpenMode)0x100).ToFileMode()); 38 | } 39 | 40 | [Test] 41 | public void ConvertToFileAccess() 42 | { 43 | Assert.AreEqual(FileAccess.Read, FileOpenMode.Read.ToFileAccess()); 44 | Assert.AreEqual(FileAccess.Write, FileOpenMode.Write.ToFileAccess()); 45 | Assert.AreEqual(FileAccess.Write, FileOpenMode.Append.ToFileAccess()); 46 | Assert.AreEqual(FileAccess.ReadWrite, FileOpenMode.ReadWrite.ToFileAccess()); 47 | Assert.Throws(() => ((FileOpenMode)0x100).ToFileAccess()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Plugins/LocateTypesExamples.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Plugins; 21 | 22 | using Yarhl.FileFormat; 23 | using Yarhl.Plugins; 24 | 25 | public static class LocateTypesExamples 26 | { 27 | public static void FindFormats() 28 | { 29 | #region FindFormats 30 | TypeImplementationInfo[] formatsInfo = TypeLocator.Default 31 | .FindImplementationsOf(typeof(IFormat)) 32 | .ToArray(); 33 | 34 | Console.WriteLine(formatsInfo[0].Name); // e.g. Yarhl.IO.BinaryFormat 35 | Console.WriteLine(formatsInfo[0].Type); // e.g. Type object for BinaryFormat 36 | #endregion 37 | } 38 | 39 | public static void FindConverters() 40 | { 41 | #region FindConverters 42 | GenericTypeImplementationInfo[] convertersInfo = TypeLocator.Default 43 | .FindImplementationsOfGeneric(typeof(IConverter<,>)) 44 | .ToArray(); 45 | 46 | Console.WriteLine(convertersInfo[0].Name); // e.g. Yarhl.Media.Text.Binary2Po 47 | Console.WriteLine(convertersInfo[0].Type); // e.g. Type object for Yarhl.Media.Text.Binary2Po 48 | Console.WriteLine(convertersInfo[0].GenericBaseType); // e.g. Type IConverter 49 | Console.WriteLine(convertersInfo[0].GenericTypeParameters); // e.g. [BinaryFormat, Po] 50 | #endregion 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileFormat/ConvertFormatTests.FormatInheritance.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.FileFormat; 2 | 3 | using System; 4 | using NUnit.Framework; 5 | using Yarhl.FileFormat; 6 | 7 | public partial class ConvertFormatTests 8 | { 9 | [Test] 10 | public void ConvertToBaseWithDerivedConverter() 11 | { 12 | // The converter will generate a derived type and cast-down to base. 13 | BaseFormat val = null; 14 | Assert.DoesNotThrow(() => val = ConvertFormat.With(typeof(ConvertDerivedFormat), (ushort)3) as BaseFormat); 15 | Assert.IsInstanceOf(val); 16 | Assert.AreEqual(3, val.X); 17 | 18 | Assert.DoesNotThrow(() => val = ConvertFormat.With(typeof(ConvertBaseFormat), 3) as BaseFormat); 19 | Assert.IsInstanceOf(val); 20 | Assert.AreEqual(5, val.X); 21 | } 22 | 23 | [Test] 24 | public void ConvertFromBaseWithDerivedConverterThrows() 25 | { 26 | // We cannot do the inverse, from base type use the derived converter 27 | BaseFormat val = new BaseFormat { X = 3 }; 28 | Assert.Throws( 29 | () => ConvertFormat.With(typeof(ConvertDerivedFormat), val)); 30 | } 31 | 32 | [Test] 33 | public void ConvertToDerivedWithDerivedConverter() 34 | { 35 | // Just to validate converter, derived with derived converter 36 | DerivedFormat derived = null; 37 | Assert.DoesNotThrow(() => derived = ConvertFormat.With(typeof(ConvertDerivedFormat), (ushort)4) as DerivedFormat); 38 | Assert.AreEqual(5, derived.Y); 39 | Assert.AreEqual(4, derived.X); 40 | 41 | ushort conv = 0; 42 | Assert.DoesNotThrow(() => conv = (ushort)ConvertFormat.With(typeof(ConvertDerivedFormat), derived)); 43 | Assert.AreEqual(5, conv); 44 | } 45 | 46 | [Test] 47 | public void ConvertFromDerivedWithBaseConverter() 48 | { 49 | var format = new DerivedFormat { Y = 11, X = 10 }; 50 | int conv = 0; 51 | 52 | Assert.DoesNotThrow(() => conv = (int)ConvertFormat.With(typeof(ConvertBaseFormat), format)); 53 | Assert.AreEqual(15, conv); 54 | } 55 | 56 | [Test] 57 | public void ConvertFromImplementationWithInterfaceFormatConverter() 58 | { 59 | var format = new InterfaceImpl { Z = 14 }; 60 | int conv = 0; 61 | Assert.DoesNotThrow(() => conv = (int)ConvertFormat.With(typeof(ConverterInterface), format)); 62 | Assert.AreEqual(14, conv); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Tutorial/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples.Tutorial; 21 | 22 | using Yarhl.FileSystem; 23 | using Yarhl.IO; 24 | using Yarhl.Media.Text; 25 | 26 | public static class Program 27 | { 28 | public static void FakeMain(string[] args) 29 | { 30 | #region OpenFile 31 | DataStream fileStream = DataStreamFactory.FromFile(args[0], FileOpenMode.Read); 32 | using var binaryFormat = new BinaryFormat(fileStream); 33 | #endregion 34 | 35 | #region Deserialize 36 | var deserializer = new Binary2Txti(); 37 | var txti = deserializer.Convert(binaryFormat); 38 | 39 | Console.WriteLine($"Number of entries: {txti.Entries.Count}"); 40 | Console.WriteLine($"First text: '{txti.Entries[0].Text}'"); 41 | #endregion 42 | } 43 | 44 | public static void FakeMain2(string[] args) 45 | { 46 | #region ExportNodes 47 | // Create a node from a file (BinaryFormat) 48 | using Node node = NodeFactory.FromFile(args[0], FileOpenMode.Read); 49 | 50 | // Transform chaining conversions fluent-like. 51 | node.TransformWith(new Binary2Txti()) 52 | .TransformWith(new Txti2Po()) 53 | .TransformWith(new Po2Binary()); 54 | 55 | // Save our new binary data into disk 56 | node.Stream!.WriteTo(args[1]); 57 | #endregion 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Yarhl/FileSystem/Node.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileSystem; 21 | 22 | using System; 23 | using Yarhl.FileFormat; 24 | 25 | /// 26 | /// Obsoleted methods in version 4. 27 | /// To be removed before next major. 28 | /// 29 | public partial class Node 30 | { 31 | /// 32 | /// Transform the node format to another format with a given converter 33 | /// initialized with parameters. 34 | /// 35 | /// This node. 36 | /// The type of the converter to use. 37 | /// The type for initializing the converter. 38 | /// Parameters to initialize the converter. 39 | [Obsolete("IInitialize is obsolete. Use the converter constructor and TransformWith(converter)")] 40 | public Node TransformWith(TParam param) 41 | where TConv : IConverter, IInitializer, new() 42 | { 43 | if (Disposed) 44 | throw new ObjectDisposedException(nameof(Node)); 45 | 46 | if (Format == null) { 47 | throw new InvalidOperationException( 48 | "Cannot transform a node without format"); 49 | } 50 | 51 | object result = ConvertFormat.With(param, Format); 52 | CastAndChangeFormat(result); 53 | 54 | return this; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryBooleanAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Define how to read and write a boolean value. 26 | /// Default type is 27 | /// 28 | [AttributeUsage(AttributeTargets.Property)] 29 | public sealed class BinaryBooleanAttribute : Attribute 30 | { 31 | /// 32 | /// Initializes a new instance of the class. 33 | /// 34 | public BinaryBooleanAttribute() 35 | { 36 | UnderlyingType = typeof(int); 37 | TrueValue = 1; 38 | FalseValue = 0; 39 | } 40 | 41 | /// 42 | /// Gets or sets the underlying type to use to serialize and deserialize. 43 | /// 44 | public Type UnderlyingType { 45 | get; 46 | set; 47 | } 48 | 49 | /// 50 | /// Gets or sets the value equals to true. 51 | /// 52 | public object TrueValue { 53 | get; 54 | set; 55 | } 56 | 57 | /// 58 | /// Gets or sets the value equals to false. 59 | /// 60 | public object FalseValue { 61 | get; 62 | set; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/Plugins/FileFormat/TestConvertersDefinition.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.Plugins.FileFormat; 2 | 3 | using System; 4 | using Yarhl.FileFormat; 5 | 6 | #pragma warning disable SA1649 // File name match type name 7 | 8 | public class MySourceFormat : IFormat 9 | { 10 | } 11 | 12 | public class MyDestFormat : IFormat 13 | { 14 | } 15 | 16 | public class DerivedSourceFormat : MySourceFormat 17 | { 18 | } 19 | 20 | public class DerivedDestFormat : IFormat 21 | { 22 | } 23 | 24 | public class MyConverter : IConverter 25 | { 26 | public MyDestFormat Convert(MySourceFormat source) 27 | { 28 | return new MyDestFormat(); 29 | } 30 | } 31 | 32 | public class MyConverterParametrized : IConverter 33 | { 34 | public MyConverterParametrized(bool ignoreMe) 35 | { 36 | } 37 | 38 | public MyDestFormat Convert(MySourceFormat source) 39 | { 40 | return new MyDestFormat(); 41 | } 42 | } 43 | 44 | public class SingleOuterConverter : IConverter 45 | { 46 | public MyDestFormat Convert(MySourceFormat source) 47 | { 48 | return new MyDestFormat(); 49 | } 50 | 51 | public class SingleInnerConverter : IConverter 52 | { 53 | public MyDestFormat Convert(MySourceFormat source) 54 | { 55 | return new MyDestFormat(); 56 | } 57 | } 58 | } 59 | 60 | public sealed class ConverterAndOtherInterface : 61 | IConverter, 62 | IDisposable 63 | { 64 | public MyDestFormat Convert(MySourceFormat source) 65 | { 66 | return new MyDestFormat(); 67 | } 68 | 69 | public void Dispose() 70 | { 71 | GC.SuppressFinalize(this); 72 | } 73 | } 74 | 75 | public class TwoConverters : 76 | IConverter, 77 | IConverter 78 | { 79 | public MyDestFormat Convert(MySourceFormat source) 80 | { 81 | return new MyDestFormat(); 82 | } 83 | 84 | public MySourceFormat Convert(MyDestFormat source) 85 | { 86 | return new MySourceFormat(); 87 | } 88 | } 89 | 90 | public abstract class BaseAbstractConverter : IConverter 91 | { 92 | public MyDestFormat Convert(MySourceFormat source) 93 | { 94 | return new MyDestFormat(); 95 | } 96 | } 97 | 98 | public class DerivedConverter : BaseAbstractConverter 99 | { 100 | } 101 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | SceneGate 4 | SceneGate 5 | Copyright (C) 2019 SceneGate 6 | 7 | true 8 | 9 | 11 | false 12 | 13 | 14 | 15 | MIT 16 | https://scenegate.github.io/Yarhl/ 17 | https://github.com/SceneGate/Yarhl 18 | icon.png 19 | binary;encoding;text;translation;localization;reverse-engineering 20 | README.md 21 | 22 | 23 | 24 | 25 | 26 | true 27 | 28 | 29 | true 30 | 31 | 37 | embedded 38 | 39 | 40 | true 41 | true 42 | 43 | 44 | 45 | 46 | true 47 | true 48 | true 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/IO/NumericExtensionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.IO 21 | { 22 | using NUnit.Framework; 23 | using Yarhl.IO; 24 | 25 | [TestFixture] 26 | public class NumericExtensionTests 27 | { 28 | [Test] 29 | public void PadUInt64() 30 | { 31 | Assert.AreEqual(0x123456789C, 0x123456789Au.Pad(4)); 32 | Assert.AreEqual(0x123456789C, 0x123456789Cu.Pad(4)); 33 | } 34 | 35 | [Test] 36 | public void PadInt64() 37 | { 38 | Assert.AreEqual(0x123456789C, 0x123456789A.Pad(4)); 39 | Assert.AreEqual(0x123456789C, 0x123456789C.Pad(4)); 40 | } 41 | 42 | [Test] 43 | public void PadUInt32() 44 | { 45 | Assert.AreEqual(0x1234567C, 0x1234567Au.Pad(4)); 46 | Assert.AreEqual(0x1234567C, 0x1234567Cu.Pad(4)); 47 | } 48 | 49 | [Test] 50 | public void PadInt32() 51 | { 52 | Assert.AreEqual(0x1234567C, 0x1234567A.Pad(4)); 53 | Assert.AreEqual(0x1234567C, 0x1234567C.Pad(4)); 54 | } 55 | 56 | [Test] 57 | public void PadUInt16() 58 | { 59 | Assert.AreEqual(0x123C, ((ushort)0x123A).Pad(4)); 60 | Assert.AreEqual(0x123C, ((ushort)0x123C).Pad(4)); 61 | } 62 | 63 | [Test] 64 | public void PadInt16() 65 | { 66 | Assert.AreEqual(0x123C, ((short)0x123A).Pad(4)); 67 | Assert.AreEqual(0x123C, ((short)0x123C).Pad(4)); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Yarhl/IO/Serialization/Attributes/BinaryStringAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.Serialization.Attributes 21 | { 22 | using System; 23 | 24 | /// 25 | /// Define how to read and write a string value. 26 | /// 27 | [AttributeUsage(AttributeTargets.Property)] 28 | public sealed class BinaryStringAttribute : Attribute 29 | { 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | public BinaryStringAttribute() 34 | { 35 | CodePage = -1; 36 | Terminator = "\0"; 37 | FixedSize = -1; 38 | MaxSize = -1; 39 | SizeType = null; 40 | } 41 | 42 | /// 43 | /// Gets or sets the string code page. 44 | /// Set to -1 to use the reader/writer encoding. 45 | /// 46 | public int CodePage { 47 | get; 48 | set; 49 | } 50 | 51 | /// 52 | /// Gets or sets the string terminator. 53 | /// 54 | public string Terminator { 55 | get; 56 | set; 57 | } 58 | 59 | /// 60 | /// Gets or sets the fixed size (in bytes) of the string. 61 | /// Set to -1 if the string is length variable. 62 | /// 63 | public int FixedSize { 64 | get; 65 | set; 66 | } 67 | 68 | /// 69 | /// Gets or sets the max size (in bytes) of the string. 70 | /// Set to -1 if the string has no max size. 71 | /// 72 | public int MaxSize { 73 | get; 74 | set; 75 | } 76 | 77 | /// 78 | /// Gets or sets the size value type. 79 | /// Set to null if string doesn't have the length serialized. 80 | /// 81 | public Type? SizeType { 82 | get; 83 | set; 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileSystem/NavigableNodeCollectionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.FileSystem 21 | { 22 | using System.Collections.Generic; 23 | using NUnit.Framework; 24 | using Yarhl.FileSystem; 25 | 26 | [TestFixture] 27 | public class NavigableNodeCollectionTests 28 | { 29 | [Test] 30 | public void GetElementAsList() 31 | { 32 | var children = new List(); 33 | var collection = new NavigableNodeCollection(children); 34 | Assert.IsEmpty(collection); 35 | 36 | children.Add(new DummyNavigable("Child1")); 37 | children.Add(new DummyNavigable("Child2")); 38 | children.Add(new DummyNavigable("Child3")); 39 | Assert.AreEqual(3, collection.Count); 40 | Assert.AreSame(children[0], collection[0]); 41 | Assert.AreSame(children[1], collection[1]); 42 | Assert.AreSame(children[2], collection[2]); 43 | } 44 | 45 | [Test] 46 | public void GetNodesByName() 47 | { 48 | var children = new List(); 49 | var collection = new NavigableNodeCollection(children); 50 | children.Add(new DummyNavigable("Child1")); 51 | children.Add(new DummyNavigable("Child2")); 52 | children.Add(new DummyNavigable("Child3")); 53 | Assert.AreSame(children[0], collection["Child1"]); 54 | Assert.AreSame(children[1], collection["Child2"]); 55 | Assert.AreSame(children[2], collection["Child3"]); 56 | } 57 | 58 | [Test] 59 | public void UnknownNameReturnsNull() 60 | { 61 | var children = new List(); 62 | var collection = new NavigableNodeCollection(children); 63 | Assert.IsNull(collection["Child1"]); 64 | } 65 | 66 | class DummyNavigable : NavigableNode 67 | { 68 | public DummyNavigable(string name) 69 | : base(name) 70 | { 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileSystem/NodeTests.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.FileSystem; 2 | 3 | using System; 4 | using System.Globalization; 5 | using NUnit.Framework; 6 | using Yarhl.FileSystem; 7 | using Yarhl.UnitTests.FileFormat; 8 | 9 | public partial class NodeTests 10 | { 11 | [Test] 12 | public void TransformWithInit() 13 | { 14 | var dummyFormat = new StringFormat("C0"); 15 | using var node = new Node("mytest", dummyFormat); 16 | 17 | _ = node.TransformWith(NumberStyles.HexNumber); 18 | Assert.IsInstanceOf(node.Format); 19 | Assert.AreNotSame(dummyFormat, node.Format); 20 | Assert.AreEqual(192, node.GetFormatAs().Value); 21 | } 22 | 23 | [Test] 24 | public void TransformWithInitReturnsNode() 25 | { 26 | var dummyFormat = new StringFormat("3"); 27 | using var node = new Node("mytest", dummyFormat); 28 | 29 | Assert.That( 30 | node.TransformWith(NumberStyles.HexNumber), 31 | Is.SameAs(node)); 32 | } 33 | 34 | [Test] 35 | public void TransformWithInitDoesNotThrowIfReturnsNull() 36 | { 37 | var dummy = new NullSource(); 38 | using var node = new Node("mytest", dummy); 39 | 40 | Assert.That( 41 | () => node.TransformWith(null), 42 | Throws.Nothing); 43 | Assert.That(node.Format, Is.Null); 44 | } 45 | 46 | [Test] 47 | public void TransformWithInitializerInterfaceThrowsIfNoConverterImplementation() 48 | { 49 | var dummyFormat = new StringFormat("3"); 50 | using var node = new Node("mytest", dummyFormat); 51 | 52 | const string msg = "Converter doesn't implement IConverter<,>"; 53 | Assert.That( 54 | () => node.TransformWith(0), 55 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 56 | } 57 | 58 | [Test] 59 | public void TransformWithInitializerInterfaceThrowsIfConverterDoesNotReturnIFormat() 60 | { 61 | var dummy = new StringFormat("3"); 62 | using var node = new Node("mytest", dummy); 63 | 64 | Assert.That( 65 | () => node.TransformWith(2), 66 | Throws.InvalidOperationException); 67 | } 68 | 69 | [Test] 70 | public void TransformWithInitializerInterfaceAfterDisposeThrowsException() 71 | { 72 | using var dummyFormat = new StringFormat("3"); 73 | var node = new Node("mytest", dummyFormat); 74 | node.Dispose(); 75 | 76 | Assert.That( 77 | () => node.TransformWith(NumberStyles.Number), 78 | Throws.TypeOf()); 79 | } 80 | 81 | [Test] 82 | public void TransformWithInitializerInterfaceWithoutFormatThrowException() 83 | { 84 | const string msg = "Cannot transform a node without format"; 85 | using var node = new Node("mytest"); 86 | 87 | Assert.That( 88 | () => node.TransformWith(NumberStyles.Integer), 89 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of 9 | experience, nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or reject 41 | comments, commits, code, wiki edits, issues, and other contributions that are 42 | not aligned to this Code of Conduct, or to ban temporarily or permanently any 43 | contributor for other behaviors that they deem inappropriate, threatening, 44 | offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at . The project 59 | team will review and investigate all complaints, and will respond in a way that 60 | it deems appropriate to the circumstances. The project team is obligated to 61 | maintain confidentiality with regard to the reporter of an incident. Further 62 | details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 71 | version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/FileSystem/NodeTransformWithInterfaces.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.PerformanceTests.FileSystem; 2 | 3 | using System; 4 | using BenchmarkDotNet.Attributes; 5 | using Yarhl.FileFormat; 6 | using Yarhl.FileSystem; 7 | using Yarhl.IO; 8 | 9 | [MemoryDiagnoser] 10 | public class NodeTransformWithInterfaces 11 | { 12 | private EnhancedNode testNode; 13 | private NoopConverter testConverter; 14 | 15 | [GlobalSetup] 16 | public void Setup() 17 | { 18 | testNode = new EnhancedNode("myNode", new BinaryFormat()); 19 | testConverter = new NoopConverter(); 20 | } 21 | 22 | [GlobalCleanup] 23 | public void Cleanup() 24 | { 25 | testNode.Dispose(); 26 | } 27 | 28 | [Benchmark] 29 | public Node TransformWithDynamic() 30 | { 31 | return testNode.Candidate1_TransformWith(testConverter); 32 | } 33 | 34 | [Benchmark] 35 | public Node TransformWithTyped() 36 | { 37 | return testNode.Candidate2_TransformWith(testConverter); 38 | } 39 | 40 | private sealed class NoopConverter : 41 | IConverter, 42 | IConverter 43 | { 44 | public BinaryFormat Convert(BinaryFormat source) 45 | { 46 | return source; 47 | } 48 | 49 | public BinaryFormat Convert(NodeContainerFormat source) 50 | { 51 | // Dummy so you can't omit the generics in the call. 52 | return new BinaryFormat(); 53 | } 54 | } 55 | 56 | private sealed class EnhancedNode : Node 57 | { 58 | public EnhancedNode(string name, IFormat format) 59 | : base(name, format) 60 | { 61 | } 62 | 63 | public Node Candidate1_TransformWith(IConverter converter) 64 | { 65 | if (Disposed) 66 | throw new ObjectDisposedException(nameof(Node)); 67 | 68 | if (converter == null) 69 | throw new ArgumentNullException(nameof(converter)); 70 | 71 | if (Format is null) { 72 | throw new InvalidOperationException( 73 | "Cannot transform a node without format"); 74 | } 75 | 76 | ConvertFormat.ValidateConverterType(converter.GetType(), Format.GetType()); 77 | 78 | dynamic converterDyn = converter; 79 | dynamic source = Format; 80 | IFormat newFormat = converterDyn.Convert(source); 81 | 82 | ChangeFormat(newFormat); 83 | 84 | return this; 85 | } 86 | 87 | public Node Candidate2_TransformWith(IConverter converter) 88 | where TSrc : IFormat 89 | where TDst : IFormat 90 | { 91 | if (Disposed) 92 | throw new ObjectDisposedException(nameof(Node)); 93 | 94 | if (converter == null) 95 | throw new ArgumentNullException(nameof(converter)); 96 | 97 | if (Format is null) { 98 | throw new InvalidOperationException( 99 | "Cannot transform a node without format"); 100 | } 101 | 102 | ConvertFormat.ValidateConverterType(converter.GetType(), Format.GetType()); 103 | 104 | TDst newFormat = converter.Convert((TSrc)Format); 105 | ChangeFormat(newFormat); 106 | 107 | return this; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/Media/Text/Encodings/SpanStreamTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.UnitTests.Media.Text.Encodings; 21 | 22 | using System; 23 | using NUnit.Framework; 24 | using Yarhl.Media.Text.Encodings; 25 | 26 | [TestFixture] 27 | public class SpanStreamTests 28 | { 29 | [Test] 30 | public void WriteValue() 31 | { 32 | var buffer = new byte[1]; 33 | var stream = new SpanStream(buffer); 34 | 35 | stream.Write(0xCA); 36 | 37 | Assert.That(stream.Length, Is.EqualTo(1)); 38 | Assert.That(buffer[0], Is.EqualTo(0xCA)); 39 | } 40 | 41 | [Test] 42 | public void WriteValueOutOfBound() 43 | { 44 | Assert.That( 45 | () => { 46 | var buffer = new byte[1]; 47 | var stream = new SpanStream(buffer); 48 | stream.Write(0xCA); 49 | stream.Write(0xFE); 50 | }, 51 | Throws.InstanceOf()); 52 | } 53 | 54 | [Test] 55 | public void WriteValues() 56 | { 57 | var buffer = new byte[2]; 58 | var stream = new SpanStream(buffer); 59 | 60 | var data = new byte[2] { 0xCA, 0xFE }; 61 | stream.Write(data); 62 | 63 | Assert.That(stream.Length, Is.EqualTo(2)); 64 | Assert.That(buffer[0], Is.EqualTo(0xCA)); 65 | Assert.That(buffer[1], Is.EqualTo(0xFE)); 66 | } 67 | 68 | [Test] 69 | public void WriteValuesOutOfBound() 70 | { 71 | Assert.That( 72 | () => { 73 | var buffer = new byte[2]; 74 | var stream = new SpanStream(buffer); 75 | 76 | var data = new byte[] { 0xCA, 0xFE, 0xFE }; 77 | stream.Write(data); 78 | }, 79 | Throws.InstanceOf()); 80 | } 81 | 82 | [Test] 83 | public void CountValue() 84 | { 85 | var stream = new SpanStream(Span.Empty); 86 | 87 | stream.Write(0xCA); 88 | 89 | Assert.That(stream.Length, Is.EqualTo(1)); 90 | } 91 | 92 | [Test] 93 | public void CountValues() 94 | { 95 | var stream = new SpanStream(Span.Empty); 96 | 97 | var data = new byte[2] { 0xCA, 0xFE }; 98 | stream.Write(data); 99 | 100 | Assert.That(stream.Length, Is.EqualTo(2)); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Yarhl/IO/StreamFormat/RecyclableMemoryStream.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO.StreamFormat 21 | { 22 | using System; 23 | using Microsoft.IO; 24 | 25 | /// 26 | /// In-memory stream with a pool of buffers. 27 | /// 28 | public sealed class RecyclableMemoryStream : StreamWrapper 29 | { 30 | static readonly RecyclableMemoryStreamManager Manager = CreateManager(); 31 | 32 | /// 33 | /// Initializes a new instance of the 34 | /// class. 35 | /// 36 | public RecyclableMemoryStream() 37 | : base(Manager.GetStream()) 38 | { 39 | } 40 | 41 | /// 42 | /// Sets the length of the stream. 43 | /// 44 | /// The new length of the stream. 45 | public override void SetLength(long value) 46 | { 47 | if (Disposed) 48 | throw new ObjectDisposedException(nameof(RecyclableMemoryStream)); 49 | 50 | long oldLength = Length; 51 | int additionalLength = (int)(value - oldLength); 52 | base.SetLength(value); 53 | 54 | // Since we are reusing buffers from a pool, it's not guarantee 55 | // that requesting more space will return a clean buffer. 56 | if (additionalLength > 0) { 57 | ClearBuffer(oldLength, additionalLength); 58 | } 59 | } 60 | 61 | static RecyclableMemoryStreamManager CreateManager() 62 | { 63 | return new RecyclableMemoryStreamManager(); 64 | } 65 | 66 | void ClearBuffer(long offset, long size) 67 | { 68 | long oldPos = Position; 69 | Position = offset; 70 | 71 | const int BufferSize = 70 * 1024; 72 | byte[] buffer = new byte[size > BufferSize ? BufferSize : size]; 73 | 74 | int written = 0; 75 | do { 76 | int loopLength; 77 | if (written + buffer.Length > size) { 78 | loopLength = (int)(size - written); 79 | } else { 80 | loopLength = buffer.Length; 81 | } 82 | 83 | Write(buffer, 0, loopLength); 84 | written += loopLength; 85 | } while (written != size); 86 | 87 | Position = oldPos; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileFormat/FormatExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.FileFormat; 2 | 3 | using System.Globalization; 4 | using FluentAssertions; 5 | using NUnit.Framework; 6 | using Yarhl.FileFormat; 7 | 8 | [TestFixture] 9 | public class FormatExtensionsTests 10 | { 11 | [Test] 12 | public void ConvertWithConvertsFormat() 13 | { 14 | using var source = new StringFormat("3"); 15 | using var expected = new IntFormat(3); 16 | 17 | IntFormat actual = source.ConvertWith(new StringFormat2IntFormat()); 18 | 19 | actual.Should().BeEquivalentTo(expected); 20 | } 21 | 22 | [Test] 23 | public void ConvertWithAllowsParameters() 24 | { 25 | using var source = new StringFormat("C0"); 26 | using var expected = new IntFormat(0xC0 + 5); 27 | 28 | IntFormat actual = source.ConvertWith( 29 | new StringFormatConverterWithConstructor(NumberStyles.HexNumber, 5)); 30 | 31 | actual.Should().BeEquivalentTo(expected); 32 | } 33 | 34 | [Test] 35 | public void ConvertWithAllowsChaining() 36 | { 37 | using var source = new StringFormat("C0"); 38 | using var expected = new StringFormat("197"); 39 | 40 | StringFormat actual = source 41 | .ConvertWith( 42 | new StringFormatConverterWithConstructor(NumberStyles.HexNumber, 5)) 43 | .ConvertWith(new IntFormat2StringFormat()); 44 | 45 | actual.Should().BeEquivalentTo(expected); 46 | } 47 | 48 | [Test] 49 | public void ConvertWithDoesNotDisposeFormatByDefault() 50 | { 51 | using var source = new IntFormat(3); 52 | using var converter = new IntFormatDisposableConverter(); 53 | 54 | StringFormat actual = source.ConvertWith(converter); 55 | 56 | Assert.Multiple(() => { 57 | Assert.That(source.Disposed, Is.False); 58 | Assert.That(actual.Disposed, Is.False); 59 | }); 60 | } 61 | 62 | [Test] 63 | public void ConvertWithDoesNotDisposeConverterByDefault() 64 | { 65 | using var source = new IntFormat(3); 66 | using var converter = new IntFormatDisposableConverter(); 67 | 68 | _ = source.ConvertWith(converter); 69 | 70 | Assert.That(converter.Disposed, Is.False); 71 | } 72 | 73 | [Test] 74 | public void ConvertWithCanDisposeFormat() 75 | { 76 | using var source = new IntFormat(3); 77 | using var converter = new IntFormatDisposableConverter(); 78 | 79 | StringFormat actual = source.ConvertWith(converter, disposeInput: true); 80 | 81 | Assert.Multiple(() => { 82 | Assert.That(source.Disposed, Is.True); 83 | Assert.That(actual.Disposed, Is.False); 84 | }); 85 | } 86 | 87 | [Test] 88 | public void ConvertWithCanDisposeConverter() 89 | { 90 | using var source = new IntFormat(3); 91 | using var converter = new IntFormatDisposableConverter(); 92 | 93 | _ = source.ConvertWith(converter, disposeConverter: true); 94 | 95 | Assert.That(converter.Disposed, Is.True); 96 | } 97 | 98 | [Test] 99 | public void ConvertWithDoesNotFailTryingToDisposeNonDisposableFormatOrConverter() 100 | { 101 | var source = new IntNonDisposableFormat(3); 102 | var converter = new IntNonDisposableFormatConverter(); 103 | 104 | Assert.That( 105 | () => _ = source.ConvertWith(converter, disposeInput: true, disposeConverter: true), 106 | Throws.Nothing); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/Encodings/japanese.txt: -------------------------------------------------------------------------------- 1 | 助ろふげ間探うむぎ掲化リタミム会本ニネハ刊進下井ノヒ合作ク以準び疑4足ナ者変ロキネサ全85習タユトヘ投辺ノ主那ッな約村リシモ約小スソ自村か善新スけ師限魚寮尼ッゃひ。被ちょせめ則短質ケヘマ畑館フヌリエ休計ドで著出マヱスル作博ヘヨ薬来ずま止月野地14創船側償な。立延じ暮心試2引ぶと前交ナ北止ム容芸たみび書著ラゃ内選でルむ県亡けにさて富次フねち起婦けひげ違面だス。 2 | 3 | 47集順6依にろで間述ワヘ他総ラ団家ヘケレ供演ーよ会生クを元74謙ンらお無能メカワ財赤ひよス体由めみスぜ馬率ミヌス制前ー工構海慈抹ス。推高好新ぎぐ動明ぱろ彰給ホ適会は一本ヱツニモ条医マキヨフ主援毎増レオ拡椎改キスハヲ忘視むほば人潤甲そつゃ。変イせとよ的著索ノカヤ真古ヲニケ子成示ふねスし自29書リヘ茂汁ルライツ集40名がこえ勉囲ンむそぼ問定うわ成傑摯晋朴ス。 4 | 5 | 経戦ユ秋界11楽8載でて初43楽9渡け出目ヨヲ票被藤ょ経35界べん崎注我よろふを公振命べ。職フ向参分未びゅそ者庫だ成度せふり情援メヲチ諭簡ホカニコ近武加うぶざき挑談で来権ヒイシヤ茶剣リーみ政際はぞ読行ヌト上呼ぱぶレ中会ど千勝ぱ真明壊層恐侑きざひ。銀ラ況表モタメウ礎央っさやで保医チル問道スヨ受返テカミモ子少アコナリ上百注ヲ土高カヘ聞一キツ徹持フ外俸ッ。 6 | 7 | 35続クヒ込者ウモサユ討5更ーち研拠ソレモタ当応けにイ流准ばまド掲改あもろか善生ナ前起トケネソ遅産ぞト用規ふ賊推ぴわん東均ヌヒ雪争キヤネミ同圧腕企ヘナエカ供時刃尿憎るドど。方べきンク注育イスセヘ能区トヱナ文紙モマロテ都刊れな映突4可7球にちへぎ次力復へまっ平馴ハテラ行禁作ソコア集点ソ集囚廉は。 8 | 9 | 者ょいのば果論エソ形検やーぼざ更者行ソケヒネ際携ホ糖談ぽたそ付黒ぐ首開ヱ間政阪集85不仲超1呼告声せ。15真おしきゅ米戒ノレコス来提アヤツソ暮配局ッ最確くぐふ含面むべ転織チホ工16捕チヱメ関度よー合確とひべあ載二メヱホモ政全襲おとょ人父娘汁極だ。止ケス活繰ハマナヨ韓職ほと考酒めとつざ露録山カスソフ生滋チシ月将ホ建関ンね文講ずよげつ権瀬しと高9従伊青ま安信ニメ育彼よぽク。 10 | 11 | 央あょおさ浄4末案マカエス府供と橋況カネ誘前しもかぼ著位5打フ署終ど阪物10全ウメ禁注はんゅ諮沖ぐ。紀やれぴフ情出ヘモ木大せス掲広もれょろ槌用スイのな東児ムカヲチ修目ヲニ機明フ得載手つそト賞知更うょ測条きド多描て。市ム題盟ネツシマ辺6去組ナ館講がレう国茂改ツ投23友確おひらべ空意ッ能辞カノ富倍ミモソマ浦以ちづ事質重もースょ店家ヱネエ在基をスぎ速樹ぜ。 12 | 13 | 97読うせがご末9報ご負円し由九浪創費ク療提田タヤロ招領レ熱退締宝嗣坪らぞゆ。日コノヌサ全業つぽぜ態野ヨ企42技ソヘコヤ球異カクテ民週こ毎表81件じひび掲煮テチ利直雪ごリみお重神メ当土ロ意戦問コメ国歳ルふラゆ演題をぶッ内吾暖れ。由ほだ予労ワカハ綱手せあ安好えふば女巨ヱツムセ再芸あーで港西クイマム争鹿代は止月みーきご肉探ワフ注三ハコモチ問毛ぞす党学ぞもてし施7直員昨挑だあばぞ。 14 | 15 | 話ーえ覧福みよ樫街権アニオメ梗言どねぴご中絆ッふがれ官自らどにむ道作ヱシリホ協電フ雄加勢よのひ挑語ナ誌書ノム大課めず虎官軍おへゃえ。5見ユニコ況90岐地っるでた財更安メニケウ成田のわそは沖頭すは上1松っつぼそ禁打ハヱミ条49呆實帖栩ゅに。供無ぼ上式ばみむぱ玉京ラべ保字ヨテカニ事予6務メマス図活け月須ノウミ努損奈クろルぶ等暮氏ホオキヲ面政ルミヲ座開キ転国クム就由語テ記日びかリ挙扱契絡ごは。 16 | 17 | 参はろち骨最マヘチ画残ヌヘヲロ協際承ム声和人にごぞフ供知6勝ゆせう将索ぴたに芸世づぴの劇刊ぎそー団丈ロカ処使沢ラマ芸省フマ士稿レもをし未41漢ー。指化リ著作スマタ新真ぎうラん戦教スア表岐彦へれる能年委ひてイ権背テヌキ伏月ラハナク落約るまね不標クミ芸庫スミ京76創船状森9筑スうへほ務約オイ年齢強びりたゃ。 18 | 19 | 73明えスほ型武民ご用者がつぴッ需球ムスソハ現格キサヤマ気杜加ざ更題ぱ全掲フテ載52党っむや王文ラチ毎人少ル今業害たてほラ込均ネオワカ済新ぞゃはや込介敷クいつ。変マリワウ紋今べそ事変ラ浪暮ケス予試にわだま古任ミツ収能題クサワ半多目職だぎトゆ刊84伝らリうさ析磨範憂スイみ。済ユヘ載感ざス地堂エワチ豊物よっねふ掲景ナヒツ名天ナ業1契ヒ経管白わゃち委更でつん市9秋セツフ業奪処ーべ。 20 | 21 | 雪クタスリ面細カテロワ宏格地ルちド当討シオエハ案第てせイ型9催ーゆゅ囲新るをざぶ見掲ヌ添立投フイく正周石トい模同記時とッドが検王給誌寄ぜつ。議ほめる疑権よ速優感映ちき要3更いほ枠格フ津減るほっ重限しはぜ図野ネク名聞違ヒス覧色むぶ必情スソネカ診65間ヨリ会后嘘姉でだお。味ヘ夫儀リづや断41一店建話91一ぼづでク覧労ネアタホ因夫レ家後ラヘ性始クホ図夜百イオ考自メイユク不与ごッ教恋朗臣菓ルスず。 22 | 23 | 男オ者込テ方者婚ヨツ訪景ゆとす上作ょくすラ択軍げる藤43情て勢初せたほば応携ばド印安かねリへ者止話え回告ぽンし介用ひそわ政込フソ月侍勃卑でへ。61作くびっ刊困ソ展常日ゃ葉極せむずゆ質字異妃健ネナヱ感校ヲカホ交稿スコネイ理朝ぐいぜ件必ぽびゃ全5闘ユカ掲都ぜ属5冤冶ゆよ。職激のわふま速行ヒチメ込年キ県作ク入提ツケウ強済うぴ著4執名業ウヱ業住タアロユ玉官軍郎婚ぶばゃ。 24 | 25 | 者一もょえた岩座レ適程ぼわレび載実写フヤ検損でなは日奏キミモ床玉取ぐ庫賞んッ図敬ロネカ綱意ルト分職抜爆んあさ。読71油たス今会ヤニ活19車経ヱイオラ屋経写夜ンリ容織ふん優政ソム覚芸ヨタ贈埼フユ記75学6域施英ばぱリ。児ほ央壊タワチ部当チルソ今海ホノアセ藤前け分名ぞ位問ソルチイ間目期ゃむ針主がます左質ソ窓情うゅ近福ゅあにこ賢古クト週育ん京侍ぱわくこ。 26 | 27 | 急ば真町ひ団善オケヤヒ経改減ぶフぞ航共フゆ車含ばよがび判能ムル犬福ッぴつん意知区ぐ帯都ん報訃岡ち。和めたな菱87上ヲ言市ヒマ校績んきンか家五ねなむ畳株告ばゅ熊郎トユヌ施販オマ大聞ざすかえ相薬マキ油値いさづ成機の。処つド京警率オニ部松3林シサツ首完武都ホキ県質るざなル官湾モクイマ造17時報リだひあ型伝要ク速国ワスケ治学みぱ。 28 | 29 | 路ふべしク明恋ワヤケヒ面6込んイすひ受庭ヤタユレ減文7問ソル菓辞無ろリ警票エカサ教稿んぐ都護イロニホ球麿権ワ津平おっきぱ時東はひよみ流戦ツリ分立フをむク。院まづぞ手強お社活教に宏免んてせゅ団止語54前査ヱチ費北すト急対場がりつれ果度意比林ラば。容コヒレ質長た地台ヒリキホ戦1低でつ望78興ミキハ再報ユモマ信担べる野獲ぶ川済ぱ任能カ済頭コオ氏浅も津投現コワモ年破点俣ずえぶ。 30 | 31 | 掲トナ客明をびルむ治批ま止温フ文選ラ残費オ奪安意ルし録物ヤケロ健栖チエ横送績民ソヌイモ党運ま表咲幼資既つぱれ。25権だといゃ治背拉ソ遺理つどろま同情ヨイヲル者芸ワシヲキ示碑ぜぐげた害員エサ資再す激4毎め改例マ報損ゅフ無察ん文読すきう設名ねしぽ者僚弱招べら。賞ね京連殺うリ額者ぜなゅ先法レロトヤ部5手氷師ヌ燥今をわ乗断年9明ウ松援傍剰ふ。 32 | 33 | 動ぐゃじ被変じクっ説大モ疆日ふリさす開権たゆか持体ナキニ無半8速訴こどめふ報発97家巨リち。年ぞろすス供設マイ講減ウイレツ広済ぐさッぼ掲年ウルノ掲件オリサ通違カユイ剣鎖どフ松結ド世売ノラ当統ニロリ政家も事域ムオ供20止ムノ格潮2送ごおにん当復固服こ。香ぜルぞし態吉せ違数域よフへ録家分ほ最井をぞでス択需早ばめ区先19橋道リノウ見縄レ体安アネ実発ア初化ラノタセ歯荒衝貨路と。 34 | 35 | 浪オネヤ区毎ルコヘオ実野ぼぎ政能いぞ第市ロル報53値りねー働駒崎ンへ巨逮クるしへ胆下らとり得入シ記藤でへご摩念メワモハ良側盤きも。概がっ含象マ表関てゅ営坂ウエチ展細ノモメ逸名せがぶ自99旅出業さこぽい球出トワ烈深広ぶ厚夕よすつ能長60印伝げつわ。見物げ店購ク国再ウイ予文テ詳他ミ勤著2初ロナサ農月朝サ視販道せわをゃ進震ンぱぴで未施ざなづ第格げづで分奪裏埼ス。 36 | 37 | 問選分帯チイス取止ルハ楽事野18強断てぶ公神ほッぼは住景っふせ暦電モ間念ノラヤヌ提量ア住京ぞクンい併表さげほえ稿戦づけお済努乱偉さルごの。禁っ和備い事61題アク真雪イぱぽば中6際さをるが更見へ時治ノモ追請治ケキワ呼在アコホ親娘ぎさ神7問れ近福験じクッぽ聞校ぎ。月しざね改日ユメノニ紙民もんふ推意おげ期全お際示マオ環属ヨ月明名テセエミ闇第テキ問金オルク野14正携どクを。 38 | 39 | 8新よ生胎ざそば政54女ヒクチハ記予ねょぽろ得威んびぞ導入ヒシヤ園権イら第洗扱く力口壁案トセ落隠ヨハメ自安サノヨ責材ツ下申セ図雪審ぽ。評ぱ第資べど住顕むが意腎へ展5打ラカヌ科維ムカ五文違津度うり信氏えだ年金りざま供差どっ。図表ウリヨ録4際コ投重ツミイ災示から間造柏が現美ム主本スト告無ッそ旋特ヨコタ円立あら国書サリイセ済50若伊師班っ。 -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/ConvertFormat.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat; 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | using System.Text; 26 | using System.Threading.Tasks; 27 | 28 | /// 29 | /// Obsoleted methods in version 4. 30 | /// To be removed before next major. 31 | /// 32 | public static partial class ConvertFormat 33 | { 34 | /// 35 | /// Converts the format using a converter with the specified type. 36 | /// 37 | /// Format to convert. 38 | /// Type of the converter. 39 | /// The new format. 40 | [Obsolete("Create the converter object or use the IFormat.ConvertWith() extension method.")] 41 | public static object With(dynamic src) 42 | where TConv : IConverter, new() 43 | { 44 | var converter = new TConv(); 45 | return With(converter, src); 46 | } 47 | 48 | /// 49 | /// Converts the format using a converter with the specified type 50 | /// and initialized with some parameters. 51 | /// 52 | /// Parameters to initialize the converter. 53 | /// Format to convert. 54 | /// Type of the converter. 55 | /// Type of the parameters. 56 | /// The new format. 57 | [Obsolete("Create the converter object or use the IFormat.ConvertWith() extension method.")] 58 | public static object With(TParam param, dynamic src) 59 | where TConv : IConverter, IInitializer, new() 60 | { 61 | var converter = new TConv(); 62 | converter.Initialize(param); 63 | return With(converter, src); 64 | } 65 | 66 | /// 67 | /// Converts the format using the specified converter. 68 | /// 69 | /// The new format. 70 | /// Converter to use. 71 | /// Format to convert. 72 | [Obsolete("Create the converter object or use the IFormat.ConvertWith() extension method.")] 73 | public static object With(IConverter converter, dynamic src) 74 | { 75 | ArgumentNullException.ThrowIfNull(converter); 76 | if (src is null) { 77 | throw new ArgumentNullException(nameof(src)); 78 | } 79 | 80 | ValidateConverterType(converter.GetType(), src.GetType()); 81 | 82 | return ((dynamic)converter).Convert(src); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Yarhl.Media.Text/Encodings/SpanStream.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Media.Text.Encodings; 21 | 22 | using System; 23 | using System.Diagnostics.CodeAnalysis; 24 | using System.Runtime.CompilerServices; 25 | 26 | /// 27 | /// Efficient stream-like implemented with Span. 28 | /// 29 | /// The type of the data of the stream. 30 | public readonly ref struct SpanStream 31 | { 32 | readonly Span buffer; 33 | readonly Counter position; 34 | readonly bool hasBuffer; 35 | 36 | /// 37 | /// Initializes a new instance of the struct. 38 | /// 39 | /// The buffer to write. 40 | internal SpanStream(Span buffer) 41 | { 42 | this.buffer = buffer; 43 | hasBuffer = !buffer.IsEmpty; 44 | 45 | // Position must be a reference type otherwise every time we pass this 46 | // instance in a method we will lose the last position back. 47 | position = new Counter(); 48 | } 49 | 50 | /// 51 | /// Gets the length of the current stream. 52 | /// 53 | public int Length => position.Count; 54 | 55 | /// 56 | /// Writes a value in the stream. 57 | /// 58 | /// Value to write. 59 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 60 | public void Write(T data) 61 | { 62 | // For performance reasons we create a local variable to avoid 63 | // accessing the reference type many times. 64 | int count = position.Count; 65 | if (hasBuffer) { 66 | buffer[count] = data; 67 | } 68 | 69 | position.Count = count + 1; 70 | } 71 | 72 | /// 73 | /// Writes a sequence of values in the stream. 74 | /// 75 | /// The data to write in the stream. 76 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 77 | public void Write(ReadOnlySpan data) 78 | { 79 | // For performance reasons we create a local variable to avoid 80 | // accessing the reference type many times. 81 | int count = position.Count; 82 | if (hasBuffer) { 83 | data.CopyTo(buffer[count..]); 84 | } 85 | 86 | position.Count = count + data.Length; 87 | } 88 | 89 | private sealed class Counter 90 | { 91 | // It's a public variable for performance reasons 92 | [SuppressMessage("", "SA1401:Fields should be private", Justification = "Internal and for performance reason")] 93 | internal int Count; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | Thanks for taking the time to contribute! :sparkles: 4 | 5 | In this document you will find all the information you need to make sure that 6 | the projects continues to be consistent and with great quality! 7 | 8 | > [!NOTE] 9 | > By contributing in this repository you accept the 10 | > [developer certificate of origin](https://developercertificate.org/). 11 | 12 | ## Reporting features and issues 13 | 14 | ### Issues 15 | 16 | When reporting a problem, be as specific as possible. Ideally, you should 17 | provide an small snippet of code that reproduces the issue. 18 | 19 | Please fill the default template so we can have all the required information to 20 | address the issue. 21 | 22 | ### Features 23 | 24 | Features are requested and handled as GitHub _issues_. 25 | 26 | If you want to ask for a new feature, first make sure it hasn't been reported 27 | yet by using the search box in the issue tab. Make sure that the feature aligns 28 | with the direction of the project. 29 | 30 | **Do not ask for tools for games or translations**. 31 | 32 | ## Pull Request 33 | 34 | Before starting a pull request, create an issue 35 | [requesting the feature](#features) you would like to see and implement. If you 36 | are fixing a bug, create also an issue to be able to track the problem. 37 | 38 | In the issue or feature request specify that that you would like to work on it. 39 | The team will reply as soon as possible to discuss the proposal. This guarantee 40 | the Pull Request implementation match the direction the project is going. 41 | 42 | In general, the process to create a pull request is: 43 | 44 | 1. Create an issue describing the bug or feature and state you would like to 45 | work on that. 46 | 2. The team will cheer you and/or discuss with you the issue. 47 | 3. Fork the project (if not done already). 48 | 4. Clone your forked project and create a git branch. 49 | 5. Make the necessary code changes in as many commits as you want. The commit 50 | message should follow this convention: 51 | 52 | ```plain 53 | :emoji: Short description #IssueID 54 | 55 | Long description if needed. 56 | ``` 57 | 58 | 6. Create a pull request. After reviewing your changes and making any new 59 | commits if needed, the team will approve and merge it. 60 | 61 | For a complete list of emoji description see 62 | [this repository](https://github.com/slashsBin/styleguide-git-commit-message#suggested-emojis). 63 | 64 | ## Code Guidelines 65 | 66 | The project includes a `.editorconfig` file that ensures the code style is 67 | consistent. It is supported in any modern IDE. 68 | 69 | In general, we follow the following standard guidelines with custom changes: 70 | 71 | - [Mono Code Guidelines](https://raw.githubusercontent.com/mono/website/gh-pages/community/contributing/coding-guidelines.md). 72 | - [Microsoft Framework Design Guidelines](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/) 73 | - [Microsoft C# Coding Convetions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions). 74 | 75 | And as the 76 | [mono team says](https://www.mono-project.com/community/contributing/coding-guidelines/#performance-and-readability): 77 | 78 | - It is more important to be correct than to be fast. 79 | - It is more important to be maintainable than to be fast. 80 | - Fast code that is difficult to maintain is likely going to be looked down 81 | upon. 82 | 83 | Make sure to follow these tips: 84 | 85 | - :heavy_check_mark: **DO** write documentation for any public type and method. 86 | - :heavy_check_mark: **DO** write a test for all the possible code branches of 87 | your methods. Use a TDD approach. 88 | - :heavy_check_mark: **DO** seek for the maximum test coverage. 89 | - :heavy_check_mark: **DO** clean compiler warning. 90 | -------------------------------------------------------------------------------- /src/Yarhl/IO/DataStream.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO; 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using System.IO; 25 | using System.Linq; 26 | using System.Text; 27 | using System.Threading.Tasks; 28 | using Yarhl.FileFormat; 29 | 30 | /// 31 | /// Obsoleted methods in version 4. 32 | /// To be removed before next major. 33 | /// 34 | public partial class DataStream 35 | { 36 | /// 37 | /// Move the position of the Stream. 38 | /// 39 | /// Distance to move position. 40 | /// Mode to move position. 41 | [Obsolete("Use the overload with SeekOrigin.")] 42 | public void Seek(long shift, SeekMode mode) 43 | { 44 | if (Disposed) 45 | throw new ObjectDisposedException(nameof(DataStream)); 46 | 47 | switch (mode) { 48 | case SeekMode.Current: 49 | _ = Seek(shift, SeekOrigin.Current); 50 | break; 51 | case SeekMode.Start: 52 | _ = Seek(shift, SeekOrigin.Begin); 53 | break; 54 | case SeekMode.End: 55 | _ = Seek(shift, SeekOrigin.End); 56 | break; 57 | default: 58 | throw new ArgumentOutOfRangeException(nameof(mode)); 59 | } 60 | } 61 | 62 | /// 63 | /// Push the current position into a stack and move to a new one. 64 | /// 65 | /// Distance to move position. 66 | /// Mode to move position. 67 | [Obsolete("Use the overload with SeekOrigin.")] 68 | public void PushToPosition(long shift, SeekMode mode) 69 | { 70 | if (Disposed) 71 | throw new ObjectDisposedException(nameof(DataStream)); 72 | 73 | positionStack.Push(Position); 74 | Seek(shift, mode); 75 | } 76 | 77 | /// 78 | /// Run a method in a specific position. 79 | /// This command will move into the position, run the method and return 80 | /// to the current position. 81 | /// 82 | /// Action to run. 83 | /// Position to move. 84 | /// Mode to move position. 85 | [Obsolete("Use the overload with SeekOrigin.")] 86 | public void RunInPosition(Action action, long position, SeekMode mode) 87 | { 88 | if (action == null) 89 | throw new ArgumentNullException(nameof(action)); 90 | 91 | PushToPosition(position, mode); 92 | action(); 93 | PopPosition(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Yarhl.Plugins/FileFormat/ConverterTypeInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Plugins.FileFormat; 21 | 22 | using System; 23 | 24 | /// 25 | /// Provides information from a type that implements a converter. 26 | /// 27 | public record ConverterTypeInfo( 28 | string Name, 29 | Type Type, 30 | Type InterfaceImplemented, 31 | IReadOnlyList GenericTypes) 32 | : GenericTypeImplementationInfo(Name, Type, InterfaceImplemented, GenericTypes) 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// The generic implementor information. 38 | public ConverterTypeInfo(GenericTypeImplementationInfo info) 39 | : this(info.Name, info.Type, info.GenericBaseType, info.GenericTypeParameters) 40 | { 41 | if (info.GenericTypeParameters.Count != 2) { 42 | throw new ArgumentException("Invalid number of generics. Expected 2."); 43 | } 44 | } 45 | 46 | /// 47 | /// Gets the source type the converter can convert from. 48 | /// 49 | public Type SourceType => GenericTypes[0]; 50 | 51 | /// 52 | /// Gets the destination type the converter can convert to. 53 | /// 54 | public Type DestinationType => GenericTypes[1]; 55 | 56 | /// 57 | /// Check if this converter type can convert from the given source type. 58 | /// It checks applying covariance rules. 59 | /// 60 | /// Source type for conversion. 61 | /// If this converter can realize the operation. 62 | public bool CanConvert(Type source) 63 | { 64 | ArgumentNullException.ThrowIfNull(source); 65 | 66 | return SourceType.IsAssignableFrom(source); 67 | } 68 | 69 | /// 70 | /// Check if this converter type can convert from the given source type 71 | /// into the given desination type. It checks applying covariance and 72 | /// contravariance rules. 73 | /// 74 | /// Source type for conversion. 75 | /// Destination type for conversion. 76 | /// If this converter can realize the operation. 77 | public bool CanConvert(Type source, Type dest) 78 | { 79 | ArgumentNullException.ThrowIfNull(source); 80 | ArgumentNullException.ThrowIfNull(dest); 81 | 82 | bool matchSource = SourceType.IsAssignableFrom(source); 83 | bool matchDest = dest.IsAssignableFrom(DestinationType); 84 | return matchSource && matchDest; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Yarhl/FileFormat/ConvertFormat.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.FileFormat 21 | { 22 | using System; 23 | 24 | /// 25 | /// Convert formats with converters. 26 | /// 27 | public static partial class ConvertFormat 28 | { 29 | /// 30 | /// Converts the format using a converter with the specified type. 31 | /// 32 | /// Type of the converter. 33 | /// Format to convert. 34 | /// 35 | /// Arguments for the constructor of the type if any. 36 | /// 37 | /// The new format. 38 | public static object With(Type converterType, dynamic src, params object?[] args) 39 | { 40 | ArgumentNullException.ThrowIfNull(converterType); 41 | if (src is not null) { 42 | ValidateConverterType(converterType, src.GetType()); 43 | } 44 | 45 | dynamic converter = Activator.CreateInstance(converterType, args) 46 | ?? throw new InvalidOperationException("Invalid converter type"); 47 | 48 | return converter.Convert(src); 49 | } 50 | 51 | /// 52 | /// Validates the type implements the expected interface for the input. 53 | /// 54 | /// The type of the converter. 55 | /// The type of the input. 56 | /// 57 | /// The converter does not implement the interface. 58 | /// 59 | internal static void ValidateConverterType(Type converterType, Type inputType) 60 | { 61 | Type[] converterInterfaces = converterType.GetInterfaces(); 62 | bool implementConverter = Array.Exists(converterInterfaces, i => 63 | i.IsGenericType && 64 | i.GetGenericTypeDefinition() == typeof(IConverter<,>)); 65 | if (!implementConverter) { 66 | throw new InvalidOperationException( 67 | "Converter doesn't implement IConverter<,>"); 68 | } 69 | 70 | bool canConvert = Array.Exists(converterInterfaces, i => 71 | i.IsGenericType && 72 | i.GenericTypeArguments.Length == 2 && 73 | i.GenericTypeArguments[0].IsAssignableFrom(inputType)); 74 | if (!canConvert) { 75 | throw new InvalidOperationException( 76 | $"Converter cannot convert the type: {inputType.FullName}"); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Yarhl.PerformanceTests/IO/DataStreamReadWriteTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.PerformanceTests.IO 21 | { 22 | using System; 23 | using System.IO; 24 | using BenchmarkDotNet.Attributes; 25 | using Microsoft.IO; 26 | using Yarhl.IO; 27 | 28 | public class DataStreamReadWriteTests 29 | { 30 | Stream stream; 31 | byte[] buffer; 32 | 33 | [ParamsAllValues] 34 | public StreamType StreamType { get; set; } 35 | 36 | [ParamsAllValues] 37 | public bool DataStreamWrapper { get; set; } 38 | 39 | [GlobalSetup] 40 | public void Setup() 41 | { 42 | var recyclableManager = new RecyclableMemoryStreamManager(); 43 | 44 | if (DataStreamWrapper) { 45 | stream = StreamType switch { 46 | StreamType.MemoryStream => new DataStream(new MemoryStream()), 47 | StreamType.RecyclableStream => DataStreamFactory.FromMemory(), 48 | StreamType.FileStream => DataStreamFactory.FromFile("dataStream", FileOpenMode.ReadWrite), 49 | _ => throw new NotSupportedException(), 50 | }; 51 | } else { 52 | stream = StreamType switch { 53 | StreamType.MemoryStream => new MemoryStream(), 54 | StreamType.RecyclableStream => recyclableManager.GetStream(), 55 | StreamType.FileStream => new FileStream("stream", FileMode.Create, FileAccess.ReadWrite), 56 | _ => throw new NotSupportedException(), 57 | }; 58 | } 59 | 60 | stream.Write(new byte[2048], 0, 2048); 61 | buffer = new byte[2048]; 62 | } 63 | 64 | [GlobalCleanup] 65 | public void CleanUp() 66 | { 67 | stream.Dispose(); 68 | } 69 | 70 | [Benchmark] 71 | public int ReadByte() 72 | { 73 | stream.Position = 0; 74 | return stream.ReadByte(); 75 | } 76 | 77 | [Benchmark] 78 | public int Read() 79 | { 80 | stream.Position = 0; 81 | return stream.Read(buffer, 0, buffer.Length); 82 | } 83 | 84 | [Benchmark] 85 | public int WriteByte() 86 | { 87 | stream.Position = 0; 88 | stream.WriteByte(0xCA); 89 | return -1; 90 | } 91 | 92 | [Benchmark] 93 | public int Write() 94 | { 95 | stream.Position = 0; 96 | stream.Write(buffer, 0, buffer.Length); 97 | return -1; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /docs/articles/core/formats/formats.md: -------------------------------------------------------------------------------- 1 | # Formats 2 | 3 | In Yarhl, _formats_ are _.NET classes_ that represents a model that can be 4 | converted and/or assigned into virtual files (_nodes_). 5 | 6 | ## Implement a new format 7 | 8 | A format is just a regular programming model, a _.NET class_ (or _record_), 9 | usually with properties and methods. The only requirement to have a _Yarhl 10 | format-compatible_ is to implement the empty interface 11 | [`IFormat`](xref:Yarhl.FileFormat.IFormat). 12 | 13 | [!code-csharp[format implementation](./../../../../src/Yarhl.Examples/Formats/Formats.cs?name=FormatImpl)] 14 | 15 | ## Converting formats 16 | 17 | > [!NOTE] 18 | > Check-out the [converters](./converters.md) topic to learn more about them. 19 | 20 | The _converters_ classes are responsible to convert one format into a new one. 21 | To use it, create a new instance and call its 22 | [`Convert(source)`]() method. 23 | 24 | [!code-csharp[serialize PO](./../../../../src/Yarhl.Examples/Formats/Converters.cs?name=SerializePo)] 25 | 26 | ### Fluent API 27 | 28 | An easier way, it's to use the extension method on formats 29 | `ConvertWith(converter)`. As it returns the new format, it allows to _chain 30 | conversions_: 31 | 32 | ```csharp 33 | FullImage fontImage = binaryFont 34 | .ConvertWith(new Binary2Font(FontKind.Debug)) // binary -> font model 35 | .ConvertWith(new Font2Image()); // font -> image 36 | ``` 37 | 38 | ### Converting without knowing converter at compile-time 39 | 40 | Sometimes the application doesn't know the converter type at compile-time. This 41 | could be the case of generic tools that loads assemblies in a plugin-style and 42 | select the converter type via configuration file or user interface. 43 | 44 | The static class [`ConvertFormat`](xref:Yarhl.FileFormat.ConvertFormat) provides 45 | the APIs to convert formats by passing its type object. The API uses reflection 46 | to validate the converter type and its arguments so that it throws an exception 47 | when: 48 | 49 | - the type does not implement `IConverter` 50 | - the converter cannot convert the type of the input. 51 | - the parameters does not match any constructor signature. 52 | 53 | ```csharp 54 | object inputFormat; 55 | 56 | // UI / config file loaded from same or external assembly 57 | Type converterType; 58 | object[] converterArgs; 59 | 60 | object outputFormat = ConvertFormat.With(converterType, inputFormat, converterArgs); 61 | ``` 62 | 63 | > [!IMPORTANT] 64 | > Note that as it uses reflection it's not as performant as other APIs. It also 65 | > lose the ability to have type-safe code. If one of the converter change its 66 | > interfaces or parameters between versions it may throw unexpected exceptions. 67 | 68 | ## `IFormat` interface 69 | 70 | The converter interface does not have any requirements for the types it could 71 | convert. You can theoretically implement `IConverter`. However, in 72 | order to provide some features the library expects that every format implements 73 | the _empty_ interface [`IFormat`](xref:Yarhl.FileFormat.IFormat). 74 | 75 | By using the [`IFormat`](xref:Yarhl.FileFormat.IFormat) interface it allows the 76 | APIs to: 77 | 78 | - Provide extension methods that applies to formats only (like `ConvertWith`). 79 | - Provide type discovery for _formats_ via _Yarhl.Plugins_. 80 | - Prevent unboxing performance issues. 81 | 82 | ## Working with existing models 83 | 84 | Models should implement the [`IFormat`](xref:Yarhl.FileFormat.IFormat) 85 | interface. If you have a model and cannot be modified to inherit from the 86 | interface, then it's possible to create a _format wrapper_. 87 | 88 | For instance, let's see how to provide a format-compatible class for a 89 | third-party sound format `ThirdPartyWave`: 90 | 91 | [!code-csharp[format wrapper](./../../../../src/Yarhl.Examples/Formats/Formats.cs?name=FormatWrapper)] 92 | -------------------------------------------------------------------------------- /docs/articles/plugins/locate-types.md: -------------------------------------------------------------------------------- 1 | # Locate types 2 | 3 | After [loading external .NET assemblies](./load-assembly.md) containing 4 | implementation of _formats_ and _converters_, the application can get a list of 5 | them via `ConverterLocator`. 6 | 7 | > [!NOTE] 8 | > This is only needed if the application does not know in advance the converter 9 | > to use. It can present the list to the user so it can choose. Or it can get 10 | > the converter names from a configuration file and later find the actual type 11 | > via reflection. For instance for generic Tinke-like applications. 12 | 13 | ## TypeLocator 14 | 15 | The `TypeLocator` provides features to find types that implement or inherit a 16 | given base type. It searches in the **loaded assemblies** of an 17 | `AssemblyLoadContext` instance. The default _singleton_ instance is accesible 18 | via `TypeLocator.Default` and it uses `AssemblyLoadContext.Default`. Normally 19 | you don't need to create your own instance. 20 | 21 | > [!NOTE] 22 | > .NET loads assemblies lazily, when a code to run needs them. If you need a 23 | > deterministic search consider loading every assembly from the application 24 | > path. See 25 | > [Load from executing directory](./load-assembly.md#load-from-executing-directory) 26 | > for more information. 27 | 28 | To find a list of types that inherit a given base class or implements an 29 | interface use the method 30 | [`FindImplementationsOf(Type)`](). 31 | It searches for final types, that is: **classes that are public and not 32 | abstract**. It returns information for each of these types in the _record_ 33 | [`TypeImplementationInfo`](xref:Yarhl.Plugins.TypeImplementationInfo) 34 | 35 | For instance to find every _format_ in the loaded asssemblies use: 36 | 37 | [!code-csharp[FindFormats](../../../src/Yarhl.Examples/Plugins/LocateTypesExamples.cs?name=FindFormats)] 38 | 39 | The case of a _generic base type_ is special as types may implemented it 40 | multiple. For instance a _class_ may implement `IConverter` 41 | **and** `IConverter`. Using the _generic type definition_ 42 | (`typeof(IConverter<,>)`) to find types will throw an exception. Use this method 43 | if you are searching for a specific implementation, like 44 | `typeof(IConverter)` 45 | 46 | Use the method 47 | [`FindImplementationsOfGeneric(Type)`]() 48 | to get a list of types implementing the **generic base type definition** with 49 | any type arguments. For instance in the previous example calling 50 | `FindImplementationsOfGeneric(typeof(IConverter<,>))` will return two results 51 | for that class. One for `IConverter` and a second for 52 | `IConverter`. The return type is the _record_ 53 | [`GenericTypeImplementationInfo`](xref:Yarhl.Plugins.GenericTypeImplementationInfo) 54 | 55 | [!code-csharp[FindConverters](../../../src/Yarhl.Examples/Plugins/LocateTypesExamples.cs?name=FindConverters)] 56 | 57 | ## ConverterLocator 58 | 59 | The [`ConverterLocator`](xref:Yarhl.Plugins.FileFormat.ConverterLocator) class 60 | provides a cache of formats and converters found in the loaded assemblies. 61 | During initialization (first use) it will use `TypeLocator` to find every format 62 | and converter types. The `Default` singleton instance use `TypeLocator.Default`. 63 | You can pass a custom `TypeLocator` via its public constructor. 64 | 65 | The properties 66 | [`Converters`](xref:Yarhl.Plugins.FileFormat.ConverterLocator.Converters) and 67 | [`Formats`](xref:Yarhl.Plugins.FileFormat.ConverterLocator.Formats) provides a 68 | list of the types found, so there is no need to re-scan the assemblies each 69 | time. 70 | 71 | > [!NOTE] 72 | > If a new assembly is loaded in the `AssemblyLoadContext`, the 73 | > `ConverterLocator` will need to performn a re-scan to find the new types. Make 74 | > sure to call 75 | > [`ConverterLocator.ScanAssemblies()`](xref:Yarhl.Plugins.FileFormat.ConverterLocator.ScanAssemblies) 76 | > after loading new assemblies. 77 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Yarhl, A format ResearcH Library 2 | 3 | ![Yarhl logo](./images/logo-large.png) 4 | 5 | _Yarhl_ is a set of libraries that helps to **implement and convert file 6 | formats** It empowers you with... 7 | 8 | - ♻️ ... APIs to easily **convert** between custom formats. 9 | - 📚 ... **guidelines** to implement and test custom format converters. 10 | - 🔢 ... advance **binary and text** reading / writing, encoding and 11 | serialization. 12 | - 📃 ... **standard formats** implementation like **PO** for translations. 13 | - 📂 ... virtual **file system** to unpack and pack containers efficiently. 14 | - 🔌... **plugin** API to find formats and converters in .NET assemblies. 15 | 16 | ## Usage 17 | 18 | The project has the following .NET libraries (NuGet packages via nuget.org). The 19 | libraries only support .NET LTS versions: **.NET 6.0** and **.NET 8.0**. 20 | 21 | - [![Yarhl](https://img.shields.io/nuget/v/Yarhl?label=Yarhl&logo=nuget)](https://www.nuget.org/packages/Yarhl) 22 | - `Yarhl.FileFormat`: format conversion APIs. 23 | - `Yarhl.FileSystem`: virtual file system. 24 | - `Yarhl.IO`: streams, binary and text reading / writing. 25 | - [![Yarhl.Media.Text](https://img.shields.io/nuget/v/Yarhl.Media.Text?label=Yarhl.Media.Text&logo=nuget)](https://www.nuget.org/packages/Yarhl.Media.Text) 26 | - `Yarhl.Media.Text`: translation formats and converters (Po), table replacer. 27 | - `Yarhl.Media.Text.Encoding`: _euc-jp_ and token-escaped encodings. 28 | - [![Yarhl.Plugins](https://img.shields.io/nuget/v/Yarhl.Plugins?label=Yarhl.Plugins&logo=nuget)](https://www.nuget.org/packages/Yarhl.Plugins) 29 | - `Yarhl.Plugins`: load nearby .NET assemblies and find type implementations. 30 | - `Yarhl.Plugins.FileFormat`: find formats and converters from loaded 31 | assemblies. 32 | 33 | > [!NOTE] 34 | > _Are you planning to try a preview version?_ 35 | > Check-out the 36 | > [GitHub project readme](https://github.com/SceneGate/Yarhl#install) for 37 | > details on how to setup the NuGet preview feed for SceneGate projects. 38 | 39 | ## Quick demo 40 | 41 | _Yarhl_ allows you to work with different file formats with an unified API for 42 | conversion into binary (serialization / deserialization). Let's try to create a 43 | new translatable file format 44 | [PO](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html) from 45 | [Yarhl.Media.Text](./articles/media-text/po-format.md) and save it into disk. 46 | 47 | [!code-csharp[Demo PO](./../src/Yarhl.Examples/Introduction.cs?name=Demo_Po)] 48 | 49 | It's frequent to find formats that are _containers_. _Yarhl_ allows to have a 50 | _virtual file system_ to work with its content without having to extract it into 51 | disk (saving space and time). For instance, let's open a game file from 52 | _Nintendo DS_ that contains thousand of files. Then we will navigate through its 53 | files, unpacking, decompressing and finally converting one file into _PO_. We 54 | can use the following libraries for this task: 55 | 56 | - [Ekona](https://scenegate.github.com/Ekona/): support of NDS game file system. 57 | - [LayTea](https://github.com/pleonex/LayTea): support of formats from 58 | _Professor Layton_ games. 59 | 60 | [!code-csharp[Demo containers](./../src/Yarhl.Examples/Introduction.cs?name=Demo_Containers)] 61 | 62 | ## Showcase 63 | 64 | Some cool projects built with _Yarhl_: 65 | 66 | - [**Texim**](https://github.com/SceneGate/Texim): experimental API for image 67 | file formats. 68 | - [**Ekona**](https://scenegate.github.io/Ekona/): support Nintendo DS file 69 | formats. 70 | - [**Lemon**](https://github.com/SceneGate/Lemon/): support Nintendo 3DS file 71 | formats. 72 | - [**LayTea**](https://www.pleonex.dev/LayTea/): modding tools for _Professor 73 | Layton_ games. 74 | - [**Attack of Friday Monsters tools**](https://github.com/pleonex/AttackFridayMonsters): 75 | modding tools for _Attack of the Friday Monsters_ game. 76 | - [**Metatron**](https://github.com/TraduSquare/Metatron): translation framework 77 | for _Shin Megami Tensei_ saga games. 78 | 79 | ## License 80 | 81 | The software is licensed under the terms of the 82 | [MIT license](https://choosealicense.com/licenses/mit/). 83 | -------------------------------------------------------------------------------- /src/Yarhl/IO/NumericExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.IO 21 | { 22 | using System; 23 | 24 | /// 25 | /// Extension methods for numeric types. 26 | /// 27 | public static class NumericExtension 28 | { 29 | /// 30 | /// Pad the specified address. 31 | /// 32 | /// The address padded. 33 | /// Address to pad. 34 | /// Padding target. 35 | public static short Pad(this short address, int padding) 36 | { 37 | return (short)Pad((ulong)address, (ulong)padding); 38 | } 39 | 40 | /// 41 | /// Pad the specified address. 42 | /// 43 | /// The address padded. 44 | /// Address to pad. 45 | /// Padding target. 46 | [CLSCompliant(false)] 47 | public static ushort Pad(this ushort address, int padding) 48 | { 49 | return (ushort)Pad(address, (ulong)padding); 50 | } 51 | 52 | /// 53 | /// Pad the specified address. 54 | /// 55 | /// The address padded. 56 | /// Address to pad. 57 | /// Padding target. 58 | public static int Pad(this int address, int padding) 59 | { 60 | return (int)Pad((ulong)address, (ulong)padding); 61 | } 62 | 63 | /// 64 | /// Pad the specified address. 65 | /// 66 | /// The address padded. 67 | /// Address to pad. 68 | /// Padding target. 69 | [CLSCompliant(false)] 70 | public static uint Pad(this uint address, int padding) 71 | { 72 | return (uint)Pad(address, (ulong)padding); 73 | } 74 | 75 | /// 76 | /// Pad the specified address. 77 | /// 78 | /// The address padded. 79 | /// Address to pad. 80 | /// Padding target. 81 | public static long Pad(this long address, long padding) 82 | { 83 | return (long)Pad((ulong)address, (ulong)padding); 84 | } 85 | 86 | /// 87 | /// Pad the specified address. 88 | /// 89 | /// The address padded. 90 | /// Address to pad. 91 | /// Padding target. 92 | [CLSCompliant(false)] 93 | public static ulong Pad(this ulong address, ulong padding) 94 | { 95 | return address + ((address % padding == 0) ? 0 : padding - (address % padding)); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Yarhl.UnitTests/FileFormat/ConvertFormatTests.Obsolete4.cs: -------------------------------------------------------------------------------- 1 | namespace Yarhl.UnitTests.FileFormat; 2 | 3 | using System.Globalization; 4 | using NUnit.Framework; 5 | using Yarhl.FileFormat; 6 | 7 | public partial class ConvertFormatTests 8 | { 9 | [Test] 10 | public void ConvertWithGeneric() 11 | { 12 | using var format = new StringFormat("3"); 13 | Assert.That( 14 | (ConvertFormat.With(format) as IntFormat).Value, 15 | Is.EqualTo(3)); 16 | } 17 | 18 | [Test] 19 | public void ConvertWithGenericInitializerInterface() 20 | { 21 | using var format = new StringFormat("C0"); 22 | Assert.That( 23 | (ConvertFormat.With( 24 | NumberStyles.HexNumber, 25 | format) as IntFormat)?.Value, 26 | Is.EqualTo(192)); 27 | } 28 | 29 | [Test] 30 | public void ConvertWithInstance() 31 | { 32 | using var format = new StringFormat("3"); 33 | var converter = new StringFormat2IntFormat(); 34 | Assert.That( 35 | (ConvertFormat.With(converter, format) as IntFormat)?.Value, 36 | Is.EqualTo(3)); 37 | } 38 | 39 | [Test] 40 | public void ConvertWithInstanceThrowsIfConverterIsNull() 41 | { 42 | using var format = new StringFormat("3"); 43 | StringFormat2IntFormat converter = null; 44 | Assert.That( 45 | () => ConvertFormat.With(converter, format), 46 | Throws.ArgumentNullException); 47 | } 48 | 49 | [Test] 50 | public void ConvertWithGenericAndInstanceThrowsExceptionIfNoImplementIConverter() 51 | { 52 | using var format = new StringFormat("3"); 53 | string msg = "Converter doesn't implement IConverter<,>"; 54 | 55 | Assert.That( 56 | () => ConvertFormat.With(format), 57 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 58 | Assert.That( 59 | () => ConvertFormat.With(4, format), 60 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 61 | 62 | var converter = new ConverterWithoutGenericInterface(); 63 | Assert.That( 64 | () => ConvertFormat.With(converter, format), 65 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 66 | } 67 | 68 | [Test] 69 | public void ConvertWithGenericOrInstanceThrowsIfFormatIsNull() 70 | { 71 | StringFormat format = null; 72 | 73 | Assert.That( 74 | () => ConvertFormat.With(format), 75 | Throws.ArgumentNullException); 76 | Assert.That( 77 | () => ConvertFormat.With( 78 | NumberStyles.Integer, 79 | format), 80 | Throws.ArgumentNullException); 81 | 82 | var converter = new StringFormat2IntFormat(); 83 | Assert.That( 84 | () => ConvertFormat.With(converter, format), 85 | Throws.ArgumentNullException); 86 | } 87 | 88 | [Test] 89 | public void ConvertWithGenericOrInstanceThrowsExceptionIfInvalidConverter() 90 | { 91 | using var format = new StringFormat("3"); 92 | const string msg = "Converter cannot convert the type: Yarhl.UnitTests.FileFormat.StringFormat"; 93 | 94 | Assert.That( 95 | () => ConvertFormat.With(format), 96 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 97 | Assert.That( 98 | () => ConvertFormat.With(4, format), 99 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 100 | 101 | var converter = new IntFormat2StringFormat(); 102 | Assert.That( 103 | () => ConvertFormat.With(converter, format), 104 | Throws.InvalidOperationException.With.Message.EqualTo(msg)); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Yarhl.Examples/Introduction.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 SceneGate 2 | 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | namespace Yarhl.Examples; 21 | 22 | using Yarhl.FileFormat; 23 | using Yarhl.FileSystem; 24 | using Yarhl.IO; 25 | using Yarhl.Media.Text; 26 | 27 | internal static class Introduction 28 | { 29 | internal static void ExportText(string gameFilePath) 30 | { 31 | #region Demo_Containers 32 | // 1. Read the game file system from a file (deserialize) 33 | using Node game = NodeFactory.FromFile(gameFilePath, FileOpenMode.Read) 34 | .TransformWith(); 35 | 36 | // 2. Navigate to the container that has our text file and unpack it. 37 | Node msgNode = Navigator.SearchNode(game, "data/ll/common/ll_common.darc") 38 | .TransformWith() // binary -> file system (container) 39 | .Children[2] // text file is the third file 40 | .TransformWith(); // the file is compressed with LZSS 41 | 42 | // 3. Convert its proprietary binary format into industry-standard translation format PO. 43 | // As it's a big text file, the converter splits the content into different files. 44 | msgNode.TransformWith() 45 | .TransformWith(LondonLifeRegion.Usa); 46 | 47 | foreach (var children in msgNode.Children) { 48 | // 4. Convert the PO into a binary format (serialize) and write to disk 49 | children.TransformWith() 50 | .Stream.WriteTo(children.Name + ".po"); 51 | } 52 | #endregion 53 | 54 | #region Demo_Po 55 | // Let's create a new PO format 56 | var metadata = new PoHeader("software1", "SceneGate", "es-ES"); 57 | Po translatableContent = new Po(metadata); 58 | 59 | // Now let's add one entry. 60 | var entry1 = new PoEntry("Hello world!"); 61 | entry1.Translated = "¡Hola mundo!"; 62 | translatableContent.Add(entry1); 63 | 64 | // Finally let's save the format into a file on disk 65 | var serializer = new Po2Binary(); 66 | using BinaryFormat binaryPo = serializer.Convert(translatableContent); 67 | binaryPo.Stream.WriteTo("strings.po"); 68 | #endregion 69 | } 70 | 71 | // Fake converters to avoid external dependencies 72 | private sealed class Binary2NitroRom : IConverter 73 | { 74 | } 75 | 76 | private sealed class BinaryDarc2Container : IConverter 77 | { 78 | } 79 | 80 | private sealed class DencDecompression : IConverter 81 | { 82 | } 83 | 84 | private sealed class Binary2MessageCollection : IConverter 85 | { 86 | } 87 | 88 | private sealed class MessageCollection2PoContainer : IConverter, IInitializer 89 | { 90 | public void Initialize(LondonLifeRegion parameters) => throw new NotImplementedException(); 91 | } 92 | 93 | private enum LondonLifeRegion 94 | { 95 | Usa = 0, 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /docs/articles/plugins/load-assembly.md: -------------------------------------------------------------------------------- 1 | # Loading .NET assemblies 2 | 3 | .NET provide already APIs to load additional assemblies via 4 | [`AssemblyLoadContext`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.loader.assemblyloadcontext). 5 | Yarhl provides extensions methods for `AssemblyLoadContext` to facilitate 6 | loading files from disk. 7 | 8 | You can use the main `AssemblyLoadContext` from `AssemblyLoadContext.Default` to 9 | load them. For advanced use cases, it's possible to create a new 10 | `AssemblyLoadContext` that would provide isolation. 11 | 12 | > [!TIP] 13 | > If you plan to use [`ConverterLocator`](./locate-types.md#converterlocator), 14 | > remember to call `ScanAssemblies` after loading new assemblies. 15 | 16 | 17 | 18 | > [!WARNING] 19 | > Loading a .NET assembly may load also its required dependencies. You may run 20 | > into dependency issues if they use different versions of a base library such 21 | > as Yarhl or Newtonsoft.Json. 22 | 23 | 24 | 25 | > [!IMPORTANT] 26 | > There may a security risk by loading **untrusted** assemblies from a file or a 27 | > directory. .NET does provide any security feature to validate it's not 28 | > malicious code. 29 | 30 | ## Load from file paths 31 | 32 | The method 33 | [`TryLoadFromAssemblyPath`]() 34 | will try to load the .NET assembly in the given path. If this assembly fails to 35 | load (e.g. it's not a .NET binary) it will return `null`. 36 | 37 | Similar, the method 38 | [`TryLoadFromAssembliesPath`]() 39 | will try to load every assembly in the list of paths given. If any of them fails 40 | to load, no exception will be raised and it would be skipped. 41 | 42 | Additionally, this API will skip any file where its name starts with any of the 43 | following prefixes. The goal is to prevent loading unwanted dependencies. If you 44 | want to force loading them, use `TryLoadFromAssemblyPath`. 45 | 46 | - `System.` 47 | - `Microsoft.` 48 | - `netstandard` 49 | - `nuget` 50 | - `nunit` 51 | - `testhost` 52 | 53 | ## Load from a directory 54 | 55 | The method 56 | [`TryLoadFromDirectory`]() 57 | will try to load every file in the given directory with an extension `.dll` or 58 | `.exe`. If any of them fails, no error will be reported and it would be skipped. 59 | 60 | Via an argument it's possible to configure if it should load files from the 61 | given directory or from its subdirectories recursively as well. 62 | 63 | ## Load from executing directory 64 | 65 | A common use case it's to load every assembly from the executable directory. 66 | Because .NET will load an assembly lazily, only when type actually need it, upon 67 | startup not every assembly from the executable directory could be loaded. 68 | 69 | The method 70 | [`TryLoadFromBaseLoadDirectory`]() 71 | addresses this use case by loading every `.dll` and `.exe` from the current 72 | `AppDomain.CurrentDomain.BaseDirectory`. 73 | 74 | > [!TIP] 75 | > To use _plugins_ in a _controlled way_, the application may add a set of 76 | > `PackageReference`s. After running `dotnet publish` these dependencies will be 77 | > copied to the output directory. At startup call 78 | > `AssemblyLoadContext.Default.TryLoadFromBaseLoadDirectory` to load all of 79 | > them. Otherwise, unless the application also references their types, the 80 | > assemblies will not be loaded. 81 | 82 | 83 | 84 | > [!NOTE] 85 | > It does not use `Environment.ProcessPath` because sometimes the application 86 | > (or tests) may run by passing the main library file to the `dotnet` host 87 | > application (e.g. `dotnet MyApp.dll`). In that case it would scan the 88 | > installation path of the .NET SDK instead of the application installation 89 | > directory. 90 | --------------------------------------------------------------------------------