Try out exception tags

This commit is contained in:
Matt Nadareski
2026-03-10 16:57:22 -04:00
parent 33dd159703
commit abc7193b8d
24 changed files with 264 additions and 56 deletions

View File

@@ -164,7 +164,9 @@ namespace SabreTools.IO.Compression.Blast
/// <summary>
/// Ensure there are bytes available, if possible
/// </summary>
/// <exception cref="IndexOutOfRangeException"></exception>
/// <exception cref="IndexOutOfRangeException">
/// Thrown if there are no bytes available from <see cref="_input">.
/// </exception>
private void EnsureAvailable()
{
// If there are bytes

View File

@@ -40,6 +40,9 @@ namespace SabreTools.IO.Compression.MSZIP
/// <summary>
/// Decompress source data to an output stream
/// </summary>
/// <exception cref="InvalidDataException">
/// Thrown if the signature does not match 0x4B43.
/// </exception>
public bool CopyTo(Stream source, Stream dest)
{
// Ignore unwritable streams

View File

@@ -26,6 +26,13 @@ namespace SabreTools.IO.Compression.SZDD
/// <summary>
/// Create a SZDD decompressor
/// </summary>
/// <param name="source">Source data stream</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="source"/> has a length of 0.
/// </exception>
/// <exception cref="InvalidOperationException">
/// Thrown if <paramref name="source"/> is not marked as readable.
/// </exception>
private Decompressor(Stream source)
{
// Validate the inputs
@@ -48,6 +55,12 @@ namespace SabreTools.IO.Compression.SZDD
/// <summary>
/// Create a KWAJ decompressor
/// </summary>
/// <param name="source">Source data stream</param>
/// <param name="compressionType">Compression type value</param>
/// <returns>Decompressor representing the compression type</returns>
/// <exception cref="IndexOutOfRangeException">
/// Thrown if <paramref name="compressionType"/> is not between 0x0000 and 0x0004.
/// </exception>
public static Decompressor CreateKWAJ(Stream source, ushort compressionType)
{
// Create the decompressor

View File

@@ -15,6 +15,9 @@ namespace SabreTools.IO.Encryption
/// <param name="key">Byte array representation of 128-bit encryption key</param>
/// <param name="iv">AES initial value for counter</param>
/// <returns>Initialized AES cipher</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="key"/> does not have a length of 16.
/// </exception>
public static IBufferedCipher CreateDecryptionCipher(byte[] key, byte[] iv)
{
if (key.Length != 16)
@@ -32,6 +35,9 @@ namespace SabreTools.IO.Encryption
/// <param name="key">Byte array representation of 128-bit encryption key</param>
/// <param name="iv">AES initial value for counter</param>
/// <returns>Initialized AES cipher</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="key"/> does not have a length of 16.
/// </exception>
public static IBufferedCipher CreateEncryptionCipher(byte[] key, byte[] iv)
{
if (key.Length != 16)

View File

@@ -1232,6 +1232,15 @@ namespace SabreTools.IO.Extensions
/// <summary>
/// Read a number of bytes from the byte array to a buffer
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="offset"/> or <paramref name="length"/>
/// is an invalid value.
/// </exception>
/// <exception cref="System.IO.EndOfStreamException">
/// Thrown if the requested <paramref name="offset"/> and
/// <paramref name="length"/> is greater than <paramref name="content"/>
/// length.
/// </exception>
private static byte[] ReadExactlyToBuffer(byte[] content, ref int offset, int length)
{
// If we have an invalid offset

View File

@@ -923,6 +923,10 @@ namespace SabreTools.IO.Extensions
/// <summary>
/// Write an array of bytes to the byte array
/// </summary>
/// <exception cref="System.IO.EndOfStreamException">
/// Thrown if <paramref name="offset"/> into <paramref name="content"/>
/// would not accomodate <paramref name="value"/>.
/// </exception>
private static bool WriteFromBuffer(byte[] content, ref int offset, byte[] value)
{
// Handle the 0-byte case

View File

@@ -1227,6 +1227,14 @@ namespace SabreTools.IO.Extensions
/// <summary>
/// Read a number of bytes from the stream to a buffer
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="length"/> is an invalid value.
/// </exception>
/// <exception cref="EndOfStreamException">
/// Thrown if the requested <paramref name="length"/> is greater
/// than the read bytes from <paramref name="content"/>.
/// length.
/// </exception>
private static byte[] ReadExactlyToBuffer(Stream stream, int length)
{
// If we have an invalid length

View File

@@ -15,6 +15,10 @@ namespace SabreTools.IO.Extensions
/// <param name="localName">Name of the element</param>
/// <param name="value">Value to write in the element</param>
/// <param name="throwOnError">Indicates if an error should be thrown on a missing required value</param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="throwOnError"/> is true and
/// <paramref name="value"/> is null.
/// </exception>
public static void WriteRequiredAttributeString(this XmlTextWriter writer, string localName, string? value, bool throwOnError = false)
{
// Throw an exception if we are configured to
@@ -31,6 +35,10 @@ namespace SabreTools.IO.Extensions
/// <param name="localName">Name of the element</param>
/// <param name="value">Value to write in the element</param>
/// <param name="throwOnError">Indicates if an error should be thrown on a missing required value</param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="throwOnError"/> is true and
/// <paramref name="value"/> is null.
/// </exception>
public static void WriteRequiredElementString(this XmlTextWriter writer, string localName, string? value, bool throwOnError = false)
{
// Throw an exception if we are configured to

View File

@@ -42,6 +42,9 @@ namespace SabreTools.IO
/// <summary>
/// Populate an INI file from path
/// </summary>
/// <exception cref="FileNotFoundException">
/// Thrown if <paramref name="path"/> is not a valid file.
/// </exception>
public IniFile(string path)
{
// If we don't have a file, we can't read it

View File

@@ -30,6 +30,13 @@ namespace SabreTools.IO.Matching
/// <param name="needle">Byte array representing the search</param>
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needle"/> has a length of 0.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="start"/> or <paramref name="end"/>
/// are invalid.
/// </exception>
public ContentMatch(byte[] needle, int start = 0, int end = -1)
{
// Validate the inputs
@@ -51,6 +58,13 @@ namespace SabreTools.IO.Matching
/// <param name="needle">Nullable byte array representing the search</param>
/// <param name="start">Optional starting position in the stack, defaults to 0</param>
/// <param name="end">Optional ending position in the stack, defaults to -1 (length of stack)</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needle"/> has a length of 0.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if either <paramref name="start"/> or <paramref name="end"/>
/// are invalid.
/// </exception>
public ContentMatch(byte?[] needle, int start = 0, int end = -1)
{
// Validate the inputs

View File

@@ -54,6 +54,9 @@ namespace SabreTools.IO.Matching
/// </summary>
/// <param name="needles">List of ContentMatch objects representing the comparisons</param>
/// <param name="setName">Unique name for the set</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needles"/> is empty.
/// </exception>
public ContentMatchSet(List<ContentMatch> needles, string setName)
{
// Validate the inputs
@@ -85,6 +88,9 @@ namespace SabreTools.IO.Matching
/// <param name="needles">List of ContentMatch objects representing the comparisons</param>
/// <param name="getVersion">Delegate for deriving a version on match of an array</param>
/// <param name="setName">Unique name for the set</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needles"/> is empty.
/// </exception>
public ContentMatchSet(List<ContentMatch> needles, GetArrayVersion getVersion, string setName)
{
// Validate the inputs
@@ -116,6 +122,9 @@ namespace SabreTools.IO.Matching
/// <param name="needles">List of ContentMatch objects representing the comparisons</param>
/// <param name="getVersion">Delegate for deriving a version on match of a Stream</param>
/// <param name="setName">Unique name for the set</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needles"/> is empty.
/// </exception>
public ContentMatchSet(List<ContentMatch> needles, GetStreamVersion getVersion, string setName)
{
// Validate the inputs

View File

@@ -30,6 +30,9 @@ namespace SabreTools.IO.Matching
/// <param name="needle">String representing the search</param>
/// <param name="matchCase">True to match exact casing, false otherwise</param>
/// <param name="useEndsWith">True to match the end only, false for contains</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needle"/> has a length of 0.
/// </exception>
public PathMatch(string needle, bool matchCase = false, bool useEndsWith = false)
{
// Validate the inputs

View File

@@ -41,6 +41,9 @@ namespace SabreTools.IO.Matching
/// </summary>
/// <param name="needles">List of PathMatch objects representing the comparisons</param>
/// <param name="setName">Unique name for the set</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needles"/> is empty.
/// </exception>
public PathMatchSet(List<PathMatch> needles, string setName)
{
// Validate the inputs
@@ -71,6 +74,9 @@ namespace SabreTools.IO.Matching
/// <param name="needles">List of PathMatch objects representing the comparisons</param>
/// <param name="getVersion">Delegate for deriving a version on match</param>
/// <param name="setName">Unique name for the set</param>
/// <exception cref="InvalidDataException">
/// Thrown if <paramref name="needles"/> is empty.
/// </exception>
public PathMatchSet(List<PathMatch> needles, GetPathVersion getVersion, string setName)
{
// Validate the inputs

View File

@@ -103,6 +103,10 @@ namespace SabreTools.IO.Readers
/// <summary>
/// Process the current line and extract out values
/// </summary>
/// <exception cref="InvalidDataException">
/// Thrown if an invalid line is encountered during processing
/// and <see cref="ValidateRows"/> is true.
/// </exception>
private void ProcessLine()
{
if (CurrentLine is null)

View File

@@ -102,6 +102,12 @@ namespace SabreTools.IO.Readers
/// <summary>
/// Read the header line
/// </summary>
/// <returns></returns>
/// <exception cref="InvalidOperationException">
/// Thrown if either:
/// - A header line is requested when <see cref="Header"/> is false.
/// - A header line has already been read when <see cref="Header"/> is true.
/// </exception>
public bool ReadHeader()
{
if (!Header)
@@ -116,6 +122,10 @@ namespace SabreTools.IO.Readers
/// <summary>
/// Read the next line in the separated value file
/// </summary>
/// <exception cref="InvalidDataException">
/// Thrown if an malformed line is encountered during processing
/// and <see cref="VerifyFieldCount"/> is true.
/// </exception>
public bool ReadNextLine()
{
if (_reader.BaseStream is null)
@@ -178,36 +188,44 @@ namespace SabreTools.IO.Readers
/// <summary>
/// Get the value for the current line for the current key
/// </summary>
/// <param name="key">Case-sensitive key based on header values</param>
/// <returns>Value associated with the key, null if the key doesn't exist</returns>
/// <exception cref="InvalidDataException">
/// Thrown if any required properties are missing.
/// </exception>
public string? GetValue(string key)
{
// No header means no key-based indexing
if (!Header)
throw new ArgumentException("No header expected so no keys can be used");
throw new InvalidDataException("No header expected so no keys can be used");
// If we don't have the key, return null
if (HeaderValues is null)
throw new ArgumentException($"Current line doesn't have key {key}");
throw new InvalidDataException($"Current line doesn't have key {key}");
if (!HeaderValues.Contains(key))
return null;
int index = HeaderValues.IndexOf(key);
if (Line is null)
throw new ArgumentException($"Current line doesn't have index {index}");
if (Line.Count < index)
throw new ArgumentException($"Current line doesn't have index {index}");
return Line[index];
return GetValue(index);
}
/// <summary>
/// Get the value for the current line for the current index
/// </summary>
/// <param name="index">Index into the current line</param>
/// <returns>Value associated with the index</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="index"/> is greater than the line count.
/// </exception>
/// <exception cref="InvalidDataException">
/// Thrown if any required properties are missing.
/// </exception>
public string GetValue(int index)
{
if (Line is null)
throw new ArgumentException($"Current line doesn't have index {index}");
throw new InvalidDataException($"Current line doesn't have index {index}");
if (Line.Count < index)
throw new ArgumentException($"Current line doesn't have index {index}");
throw new ArgumentOutOfRangeException($"Current line doesn't have index {index}");
return Line[index];
}

View File

@@ -1,4 +1,4 @@
using System;
using System.Data;
using System.IO;
using SabreTools.IO.Extensions;
@@ -33,6 +33,11 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Create a new BitStream from a source Stream
/// </summary>
/// <param name="source">Source stream</param>
/// <exception cref="DataException">
/// Thrown if <paramref name="source"/> is either marked
/// as unreadable or non-seekable.
/// </exception>
public ReadOnlyBitStream(Stream source)
{
_source = source;
@@ -41,7 +46,7 @@ namespace SabreTools.IO.Streams
// Verify the stream
if (!source.CanRead || !source.CanSeek)
throw new ArgumentException($"{nameof(source)} needs to be readable and seekable");
throw new DataException($"{nameof(source)} needs to be readable and seekable");
}
/// <summary>

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
namespace SabreTools.IO.Streams
@@ -42,7 +43,7 @@ namespace SabreTools.IO.Streams
#region Instance Variables
/// <summary>
/// Internal collection of streams to read from
/// Internal set of streams to read from
/// </summary>
private readonly List<Stream> _streams;
@@ -73,7 +74,11 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Create a new ReadOnlyCompositeStream from a single Stream
/// </summary>
/// <param name="stream"></param>
/// <param name="source">Source stream</param>
/// <exception cref="DataException">
/// Thrown if <paramref name="source"/> is either marked
/// as unreadable or non-seekable.
/// </exception>
public ReadOnlyCompositeStream(Stream stream)
{
_streams = [stream];
@@ -82,14 +87,19 @@ namespace SabreTools.IO.Streams
// Verify the stream and add to the length
if (!stream.CanRead || !stream.CanSeek)
throw new ArgumentException($"{nameof(stream)} needs to be readable and seekable");
throw new DataException($"{nameof(stream)} needs to be readable and seekable");
_length += stream.Length;
}
/// <summary>
/// Create a new ReadOnlyCompositeStream from an existing collection of Streams
/// Create a new ReadOnlyCompositeStream from an existing set of Streams
/// </summary>
/// <param name="streams">Set of streams</param>
/// <exception cref="DataException">
/// Thrown if any stream in <paramref name="streams"/> is
/// either marked as unreadable or non-seekable.
/// </exception>
public ReadOnlyCompositeStream(Stream[] streams)
{
_streams = [.. streams];
@@ -100,15 +110,20 @@ namespace SabreTools.IO.Streams
foreach (var stream in streams)
{
if (!stream.CanRead || !stream.CanSeek)
throw new ArgumentException($"All members of {nameof(streams)} need to be readable and seekable");
throw new DataException($"All members of {nameof(streams)} need to be readable and seekable");
_length += stream.Length;
}
}
/// <summary>
/// Create a new ReadOnlyCompositeStream from an existing collection of Streams
/// Create a new ReadOnlyCompositeStream from an existing set of Streams
/// </summary>
/// <param name="streams">Set of streams</param>
/// <exception cref="DataException">
/// Thrown if any stream in <paramref name="streams"/> is
/// either marked as unreadable or non-seekable.
/// </exception>
public ReadOnlyCompositeStream(IEnumerable<Stream> streams)
{
_streams = [.. streams];
@@ -130,7 +145,7 @@ namespace SabreTools.IO.Streams
#region Data
/// <summary>
/// Add a new stream to the collection
/// Add a new stream to the set
/// </summary>
public bool AddStream(Stream stream)
{
@@ -262,6 +277,14 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Determines if a stream contains a particular segment
/// </summary>
/// <param name="streamIndex">Index into the backing streams set</param>
/// <param name="offset">Offset in the stream to check</param>
/// <param name="length">Length of data requested at the offset</param>
/// <returns>True if the offset and length are valid, false otherwise</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="streamIndex"/>, <paramref name="offset"/>,
/// or <paramref name="length"/> are invalid.
/// </exception>
private bool StreamContains(int streamIndex, long offset, int length)
{
// Ensure the arguments are valid

View File

@@ -102,16 +102,24 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Construct a new ViewStream from a Stream
/// </summary>
public ViewStream(Stream data, long offset)
/// <param name="source">Source stream</param>
/// <param name="offset">Offset in the source to use as the starting index</param>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="source"/> is not marked as readable.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="offset"/> is invalid.
/// </exception>
public ViewStream(Stream source, long offset)
{
if (!data.CanRead)
throw new ArgumentException(nameof(data));
if (offset < 0 || offset > data.Length)
if (!source.CanRead)
throw new ArgumentException(nameof(source));
if (offset < 0 || offset > source.Length)
throw new ArgumentOutOfRangeException(nameof(offset));
_source = data;
_source = source;
_initialPosition = offset;
_length = data.Length - offset;
_length = source.Length - offset;
_source.Seek(_initialPosition, SeekOrigin.Begin);
}
@@ -119,16 +127,25 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Construct a new ViewStream from a Stream
/// </summary>
public ViewStream(Stream data, long offset, long length)
/// <param name="source">Source stream</param>
/// <param name="offset">Offset in the source to use as the starting index</param>
/// <param name="length">Length of the window</param>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="source"/> is not marked as readable.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="offset"/> or <paramref name="length"/> are invalid.
/// </exception>
public ViewStream(Stream source, long offset, long length)
{
if (!data.CanRead)
throw new ArgumentException(nameof(data));
if (offset < 0 || offset > data.Length)
if (!source.CanRead)
throw new ArgumentException(nameof(source));
if (offset < 0 || offset > source.Length)
throw new ArgumentOutOfRangeException(nameof(offset));
if (length < 0 || offset + length > data.Length)
if (length < 0 || offset + length > source.Length)
throw new ArgumentOutOfRangeException(nameof(length));
_source = data;
_source = source;
_initialPosition = offset;
_length = length;
@@ -138,13 +155,18 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Construct a new ViewStream from a byte array
/// </summary>
public ViewStream(byte[] data, long offset)
/// <param name="source">Source array</param>
/// <param name="offset">Offset in the source to use as the starting index</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="offset"/> is invalid.
/// </exception>
public ViewStream(byte[] source, long offset)
{
if (offset < 0 || offset > data.Length)
if (offset < 0 || offset > source.Length)
throw new ArgumentOutOfRangeException(nameof(offset));
long length = data.Length - offset;
_source = new MemoryStream(data, (int)offset, (int)length);
long length = source.Length - offset;
_source = new MemoryStream(source, (int)offset, (int)length);
_initialPosition = 0;
_length = length;
@@ -154,14 +176,20 @@ namespace SabreTools.IO.Streams
/// <summary>
/// Construct a new ViewStream from a byte array
/// </summary>
public ViewStream(byte[] data, long offset, long length)
/// <param name="source">Source array</param>
/// <param name="offset">Offset in the source to use as the starting index</param>
/// <param name="length">Length of the window</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="offset"/> or <paramref name="length"/> are invalid.
/// </exception>
public ViewStream(byte[] source, long offset, long length)
{
if (offset < 0 || offset > data.Length)
if (offset < 0 || offset > source.Length)
throw new ArgumentOutOfRangeException(nameof(offset));
if (length < 0 || offset + length > data.Length)
if (length < 0 || offset + length > source.Length)
throw new ArgumentOutOfRangeException(nameof(length));
_source = new MemoryStream(data, (int)offset, (int)length);
_source = new MemoryStream(source, (int)offset, (int)length);
_initialPosition = 0;
_length = length;

View File

@@ -113,6 +113,9 @@ namespace SabreTools.IO.Transform
/// <param name="output">Path to the output file</param>
/// <param name="type"><see cref="BlockSize"> representing how to process the inputs</param>
/// <returns>A filled stream on success, null otherwise</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="type"/> is not a recognized value.
/// </exception>
public static Stream? Interleave(Stream even, Stream odd, BlockSize type)
{
// If either stream is unreadable

View File

@@ -69,6 +69,9 @@ namespace SabreTools.IO.Transform
/// <param name="even">Even block output stream on success, null otherwise</param>
/// <param name="odd">Odd block output stream on success, null otherwise</param>
/// <returns>True if the stream could be split, false otherwise</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="type"/> is not a recognized value.
/// </exception>
public static bool BlockSplit(Stream input, BlockSize type, out Stream? even, out Stream? odd)
{
// Set default values for the outputs

View File

@@ -59,6 +59,9 @@ namespace SabreTools.IO.Transform
/// <param name="input">Input stream</param>
/// <param name="operation">Transform operation to carry out</param>
/// <returns>True if the file was transformed properly, false otherwise</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="type"/> is not a recognized value.
/// </exception>
public static Stream? Process(Stream input, Operation operation)
{
// If the stream is unreadable

View File

@@ -182,10 +182,10 @@ namespace SabreTools.IO.Writers
_writer.Write(name);
_writer.Write(" (");
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}
@@ -223,10 +223,10 @@ namespace SabreTools.IO.Writers
if ((quoteOverride is null && Quotes) || (quoteOverride == true))
_writer.Write("\"");
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}
@@ -239,10 +239,10 @@ namespace SabreTools.IO.Writers
{
AutoComplete(Token.EndAttribute, quoteOverride);
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}
@@ -266,6 +266,10 @@ namespace SabreTools.IO.Writers
/// <param name="value">Value to write in the attribute</param>
/// <param name="quoteOverride">Non-null to overwrite the writer setting, null otherwise</param>
/// <param name="throwOnError">Indicates if an error should be thrown on a missing required value</param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="throwOnError"/> is true and
/// <paramref name="value"/> is null.
/// </exception>
public void WriteRequiredAttributeString(string name, string? value, bool? quoteOverride = null, bool throwOnError = false)
{
// Throw an exception if we are configured to
@@ -293,6 +297,9 @@ namespace SabreTools.IO.Writers
/// <param name="name">Name of the attribute</param>
/// <param name="value">Value to write in the attribute</param>
/// <param name="quoteOverride">Non-null to overwrite the writer setting, null otherwise</param>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="name"/> is null or empty.
/// </exception>
public void WriteStandalone(string name, string? value, bool? quoteOverride = null)
{
try
@@ -324,10 +331,10 @@ namespace SabreTools.IO.Writers
_writer.Write("\"");
}
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}
@@ -338,6 +345,10 @@ namespace SabreTools.IO.Writers
/// <param name="value">Value to write in the attribute</param>
/// <param name="quoteOverride">Non-null to overwrite the writer setting, null otherwise</param>
/// <param name="throwOnError">Indicates if an error should be thrown on a missing required value</param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="throwOnError"/> is true and
/// <paramref name="value"/> is null.
/// </exception>
public void WriteRequiredStandalone(string name, string? value, bool? quoteOverride = null, bool throwOnError = false)
{
// Throw an exception if we are configured to
@@ -377,10 +388,10 @@ namespace SabreTools.IO.Writers
_writer.Write(value);
}
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}
@@ -415,6 +426,11 @@ namespace SabreTools.IO.Writers
/// <summary>
/// Prepare for the next token to be written
/// </summary>
/// <param name="token">Last token to have been processed</param>
/// <param name="quoteOverride">Non-null to overwrite the writer setting, null otherwise</param>
/// <exception cref="InvalidOperationException">
/// Thrown if the state of the writer is invalid.
/// </exception>
private void AutoComplete(Token token, bool? quoteOverride = null)
{
// Handle the error cases
@@ -508,6 +524,7 @@ namespace SabreTools.IO.Writers
/// <summary>
/// Internal helper to write the end of an element
/// </summary>
/// <param name="longFormat">Determine if a full or truncated end element is written</param>
private void InternalWriteEndElement(bool longFormat)
{
try
@@ -516,7 +533,7 @@ namespace SabreTools.IO.Writers
throw new InvalidOperationException();
AutoComplete(longFormat ? Token.LongEndElement : Token.EndElement);
if (this._lastToken == Token.LongEndElement)
if (_lastToken == Token.LongEndElement)
{
Indent(true);
_writer.Write(')');
@@ -524,10 +541,10 @@ namespace SabreTools.IO.Writers
_topPtr--;
}
catch
catch (Exception ex)
{
_currentState = State.Error;
throw;
throw ex;
}
}

View File

@@ -50,13 +50,17 @@ namespace SabreTools.IO.Writers
/// <summary>
/// Write a section tag
/// </summary>
/// <param name="value">Value to use as the section tag</param>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="value"/> is null or empty.
/// </exception>
public void WriteSection(string? value)
{
if (_writer.BaseStream is null)
return;
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Section tag cannot be null or empty", nameof(value));
throw new ArgumentNullException("Section tag cannot be null or empty", nameof(value));
_writer.WriteLine($"[{value!.TrimStart('[').TrimEnd(']')}]");
}
@@ -64,13 +68,16 @@ namespace SabreTools.IO.Writers
/// <summary>
/// Write a key value pair
/// </summary>
/// <exception cref="ArgumentNullException">
/// Thrown if <paramref name="key"/> is null or empty.
/// </exception>
public void WriteKeyValuePair(string key, string? value)
{
if (_writer.BaseStream is null)
return;
if (string.IsNullOrEmpty(key))
throw new ArgumentException("Key cannot be null or empty", nameof(key));
throw new ArgumentNullException("Key cannot be null or empty", nameof(key));
value ??= string.Empty;
_writer.WriteLine($"{key}={value}");

View File

@@ -1,4 +1,5 @@
using System;
using System.Data;
using System.IO;
using System.Text;
@@ -96,11 +97,19 @@ namespace SabreTools.IO.Writers
/// <summary>
/// Write a value row
/// </summary>
/// <param name="values">Array representing the values</param>
/// <param name="newline">True to append a newline, false otherwise</param>
/// <exception cref="ArgumentException">
/// Thrown if <see cref="Separator"/> is an invalid character.
/// </exception>
/// <exception cref="DataException">
/// Thrown if the underlying stream is not marked as writable.
/// </exception>
public void WriteValues(object?[] values, bool newline = true)
{
// If the writer can't be used, we error
if (!_writer.BaseStream.CanWrite)
throw new ArgumentException(nameof(_writer));
throw new DataException(nameof(_writer));
// If the separator character is invalid, we error
if (Separator == default(char))