From cf9de66a85191b26e7de084a39d9f95473c8072e Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 8 Sep 2023 17:03:31 -0400 Subject: [PATCH] Add and convert XML base class --- Files/XmlFile.Deserializer.cs | 22 ++++++++++++++ PathProcessor.cs | 54 +++++++++++++++++++++++++++++++++ Streams/XmlFile.Deserializer.cs | 45 +++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 Files/XmlFile.Deserializer.cs create mode 100644 PathProcessor.cs create mode 100644 Streams/XmlFile.Deserializer.cs diff --git a/Files/XmlFile.Deserializer.cs b/Files/XmlFile.Deserializer.cs new file mode 100644 index 00000000..f13df26d --- /dev/null +++ b/Files/XmlFile.Deserializer.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Files +{ + /// + /// Base class for other XML serializers + /// + /// + public partial class XmlFile : IFileSerializer + { + /// +#if NET48 + public T Deserialize(string path) +#else + public T? Deserialize(string? path) +#endif + { + using (var data = PathProcessor.OpenStream(path)) + { + return new Streams.XmlFile().Deserialize(data); + } + } + } +} \ No newline at end of file diff --git a/PathProcessor.cs b/PathProcessor.cs new file mode 100644 index 00000000..dee59422 --- /dev/null +++ b/PathProcessor.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using System.IO.Compression; + +namespace SabreTools.Serialization +{ + internal class PathProcessor + { + /// + /// Opens a path as a stream in a safe manner, decompressing if needed + /// + /// Path to open as a stream + /// Stream representing the file, null on error +#if NET48 + public static Stream OpenStream(string path) +#else + public static Stream? OpenStream(string path) +#endif + { + try + { + // If we don't have a file + if (string.IsNullOrWhiteSpace(path) || !File.Exists(path)) + return null; + + // Open the file for deserialization + var stream = File.OpenRead(path); + + // Get the extension to determine if additional handling is needed + string ext = Path.GetExtension(path).TrimStart('.'); + + // Determine what we do based on the extension + if (string.Equals(ext, "gz", StringComparison.OrdinalIgnoreCase)) + { + return new GZipStream(stream, CompressionMode.Decompress); + } + else if (string.Equals(ext, "zip", StringComparison.OrdinalIgnoreCase)) + { + // TODO: Support zip-compressed files + return null; + } + else + { + return stream; + } + } + catch + { + // TODO: Handle logging the exception + return null; + } + } + } +} \ No newline at end of file diff --git a/Streams/XmlFile.Deserializer.cs b/Streams/XmlFile.Deserializer.cs new file mode 100644 index 00000000..24087d1a --- /dev/null +++ b/Streams/XmlFile.Deserializer.cs @@ -0,0 +1,45 @@ +using System.IO; +using System.Xml; +using System.Xml.Schema; +using System.Xml.Serialization; + +namespace SabreTools.Serialization.Streams +{ + /// + /// Base class for other XML serializers + /// + /// + public partial class XmlFile : IStreamSerializer + { + /// +#if NET48 + public T Deserialize(Stream data) +#else + public T? Deserialize(Stream? data) +#endif + { + // If the stream is null + if (data == null) + return default; + + // Setup the serializer and the reader + var serializer = new XmlSerializer(typeof(T)); + var settings = new XmlReaderSettings + { + CheckCharacters = false, + DtdProcessing = DtdProcessing.Ignore, + ValidationFlags = XmlSchemaValidationFlags.None, + ValidationType = ValidationType.None, + }; + var streamReader = new StreamReader(data); + var xmlReader = XmlReader.Create(streamReader, settings); + + // Perform the deserialization and return +#if NET48 + return (T)serializer.Deserialize(xmlReader); +#else + return (T?)serializer.Deserialize(xmlReader); +#endif + } + } +} \ No newline at end of file