mirror of
https://github.com/UglyToad/PdfPig.git
synced 2025-07-15 20:16:04 +08:00
Improve Code Quality 3 (#805)
* Throw when trying to inverse a matrix with a determinant of 0 * Optimize Hex.GetString on .NET * Updates tests for Matrix3x3.Inverse() change * Eliminate allocation in InternalStringExtensions * Use vectorized Span.Fill method * Eliminate various string allocations when parsing numbers * Remove unused using statements * Fix Matrix3x3 Equals nullability
This commit is contained in:
parent
a412a239be
commit
69e2b7bb08
@ -15,7 +15,7 @@ namespace UglyToad.PdfPig.Tests.Util
|
|||||||
[InlineData("pineapple", "apple", 4, true)]
|
[InlineData("pineapple", "apple", 4, true)]
|
||||||
public void StartsWithOffset(string input, string start, int offset, bool expected)
|
public void StartsWithOffset(string input, string start, int offset, bool expected)
|
||||||
{
|
{
|
||||||
var result = input.StartsWithOffset(start, offset);
|
var result = input.StartsWithOffset(start.AsSpan(), offset);
|
||||||
|
|
||||||
Assert.Equal(expected, result);
|
Assert.Equal(expected, result);
|
||||||
}
|
}
|
||||||
@ -23,9 +23,9 @@ namespace UglyToad.PdfPig.Tests.Util
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void StartsWithOffset_NegativeOffset_Throws()
|
public void StartsWithOffset_NegativeOffset_Throws()
|
||||||
{
|
{
|
||||||
Action action = () => "any".StartsWithOffset("x", -1);
|
Action action = () => "any".StartsWithOffset("x".AsSpan(), -1);
|
||||||
|
|
||||||
Assert.Throws<ArgumentOutOfRangeException>(action);
|
Assert.Throws<ArgumentOutOfRangeException>(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -106,15 +106,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void InverseReturnsNullIfNotPossible()
|
public void InverseThrowsNotPossible()
|
||||||
{
|
{
|
||||||
var matrix = new Matrix3x3(
|
var matrix = new Matrix3x3(
|
||||||
1, 2, 3,
|
1, 2, 3,
|
||||||
4, 5, 6,
|
4, 5, 6,
|
||||||
7, 8, 9);
|
7, 8, 9);
|
||||||
|
|
||||||
var inverse = matrix.Inverse();
|
Assert.Throws<InvalidOperationException>(() => matrix.Inverse());
|
||||||
Assert.Null(inverse);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using IO;
|
using IO;
|
||||||
using Util;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
|
/// CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
|
||||||
@ -426,7 +425,7 @@
|
|||||||
{
|
{
|
||||||
if (decodedLength < 0)
|
if (decodedLength < 0)
|
||||||
{
|
{
|
||||||
ArrayHelper.Fill(b, off, off + len, (byte)0x0);
|
b.AsSpan(off, len).Fill(0x0);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,7 +435,7 @@
|
|||||||
|
|
||||||
if (decodedLength < 0)
|
if (decodedLength < 0)
|
||||||
{
|
{
|
||||||
ArrayHelper.Fill(b, off, off + len, (byte)0x0);
|
b.AsSpan(off, len).Fill(0x0);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
Method method = Method.Bradford)
|
Method method = Method.Bradford)
|
||||||
{
|
{
|
||||||
var coneReponseDomain = GetConeResponseDomain(method)!;
|
var coneReponseDomain = GetConeResponseDomain(method)!;
|
||||||
var inverseConeResponseDomain = coneReponseDomain.Inverse()!;
|
var inverseConeResponseDomain = coneReponseDomain.Inverse();
|
||||||
var (ρS, γS, βS) = coneReponseDomain.Multiply(sourceReferenceWhite);
|
var (ρS, γS, βS) = coneReponseDomain.Multiply(sourceReferenceWhite);
|
||||||
|
|
||||||
var (ρD, γD, βD) = coneReponseDomain.Multiply(destinationReferenceWhite);
|
var (ρD, γD, βD) = coneReponseDomain.Multiply(destinationReferenceWhite);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
using Logging;
|
using Logging;
|
||||||
using Tokenization.Scanner;
|
using Tokenization.Scanner;
|
||||||
using Tokens;
|
using Tokens;
|
||||||
|
using UglyToad.PdfPig.Util;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to retrieve the version header from the PDF file.
|
/// Used to retrieve the version header from the PDF file.
|
||||||
@ -70,7 +71,7 @@
|
|||||||
|
|
||||||
const int toDoubleStartLength = 4;
|
const int toDoubleStartLength = 4;
|
||||||
|
|
||||||
if (!double.TryParse(comment.Data.Substring(toDoubleStartLength),
|
if (!double.TryParse(comment.Data.AsSpanOrSubstring(toDoubleStartLength),
|
||||||
NumberStyles.Number,
|
NumberStyles.Number,
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
out var version))
|
out var version))
|
||||||
@ -118,7 +119,7 @@
|
|||||||
|
|
||||||
if (actualIndex >= 0 && content.Length - actualIndex >= versionLength)
|
if (actualIndex >= 0 && content.Length - actualIndex >= versionLength)
|
||||||
{
|
{
|
||||||
var numberPart = content.Substring(actualIndex + 5, 3);
|
var numberPart = content.AsSpanOrSubstring(actualIndex + 5, 3);
|
||||||
if (double.TryParse(
|
if (double.TryParse(
|
||||||
numberPart,
|
numberPart,
|
||||||
NumberStyles.Number,
|
NumberStyles.Number,
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
namespace UglyToad.PdfPig.Util
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
internal static class ArrayHelper
|
|
||||||
{
|
|
||||||
public static void Fill<T>(T[] array, int start, int end, T value)
|
|
||||||
{
|
|
||||||
if (array is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(array));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start < 0 || start >= end)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(start));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end >= array.Length)
|
|
||||||
{
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(end));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = start; i < end; i++)
|
|
||||||
{
|
|
||||||
array[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
namespace UglyToad.PdfPig.Util
|
namespace UglyToad.PdfPig.Util
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper class for dates.
|
/// Helper class for dates.
|
||||||
@ -53,7 +54,7 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 4), out var year))
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 4), NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -72,7 +73,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 2), out var month)
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var month)
|
||||||
|| !IsWithinRange(month, 1, 12))
|
|| !IsWithinRange(month, 1, 12))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -92,7 +93,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 2), out var day)
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var day)
|
||||||
|| !IsWithinRange(day, 1, 31))
|
|| !IsWithinRange(day, 1, 31))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -112,7 +113,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 2), out var hour)
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var hour)
|
||||||
|| !IsWithinRange(hour, 0, 23))
|
|| !IsWithinRange(hour, 0, 23))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -132,7 +133,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 2), out var minute)
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var minute)
|
||||||
|| !IsWithinRange(minute, 0, 59))
|
|| !IsWithinRange(minute, 0, 59))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -152,7 +153,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(s.Substring(location, 2), out var second)
|
if (!int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var second)
|
||||||
|| !IsWithinRange(second, 0, 59))
|
|| !IsWithinRange(second, 0, 59))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -189,7 +190,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasRemainingCharacters(location, 3) || !int.TryParse(s.Substring(location, 2), out var hoursOffset)
|
if (!HasRemainingCharacters(location, 3) || !int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var hoursOffset)
|
||||||
|| s[location + 2] != '\''
|
|| s[location + 2] != '\''
|
||||||
|| !IsWithinRange(hoursOffset, 0, 23))
|
|| !IsWithinRange(hoursOffset, 0, 23))
|
||||||
{
|
{
|
||||||
@ -205,7 +206,7 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasRemainingCharacters(location, 3) || !int.TryParse(s.Substring(location, 2), out var minutesOffset)
|
if (!HasRemainingCharacters(location, 3) || !int.TryParse(s.AsSpanOrSubstring(location, 2), NumberStyles.Integer, CultureInfo.InvariantCulture, out var minutesOffset)
|
||||||
|| s[location + 2] != '\''
|
|| s[location + 2] != '\''
|
||||||
|| !IsWithinRange(minutesOffset, 0, 59))
|
|| !IsWithinRange(minutesOffset, 0, 59))
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string GetString(ReadOnlySpan<byte> bytes)
|
public static string GetString(ReadOnlySpan<byte> bytes)
|
||||||
{
|
{
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
return Convert.ToHexString(bytes);
|
||||||
|
#else
|
||||||
var stringBuilder = new StringBuilder(bytes.Length * 2);
|
var stringBuilder = new StringBuilder(bytes.Length * 2);
|
||||||
|
|
||||||
foreach (var b in bytes)
|
foreach (var b in bytes)
|
||||||
@ -31,6 +34,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
return stringBuilder.ToString();
|
return stringBuilder.ToString();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetHighNibble(byte b)
|
private static int GetHighNibble(byte b)
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
internal static class InternalStringExtensions
|
internal static class InternalStringExtensions
|
||||||
{
|
{
|
||||||
public static bool StartsWithOffset(this string value, string start, int offset)
|
public static bool StartsWithOffset(this string value, ReadOnlySpan<char> start, int offset)
|
||||||
{
|
{
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
{
|
{
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
if (value is null)
|
if (value is null)
|
||||||
{
|
{
|
||||||
if (start is null && offset == 0)
|
if (start.Length is 0 && offset == 0)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -26,7 +26,29 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return value.Substring(offset).StartsWith(start);
|
return value.AsSpan(offset).StartsWith(start, StringComparison.Ordinal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NET
|
||||||
|
public static ReadOnlySpan<char> AsSpanOrSubstring(this string text, int start)
|
||||||
|
{
|
||||||
|
return text.AsSpan(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ReadOnlySpan<char> AsSpanOrSubstring(this string text, int start, int length)
|
||||||
|
{
|
||||||
|
return text.AsSpan(start, length);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
public static string AsSpanOrSubstring(this string text, int start)
|
||||||
|
{
|
||||||
|
return text.Substring(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AsSpanOrSubstring(this string text, int start, int length)
|
||||||
|
{
|
||||||
|
return text.Substring(start, length);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace UglyToad.PdfPig.Util
|
namespace UglyToad.PdfPig.Util
|
||||||
{
|
{
|
||||||
internal class Matrix3x3 : IEnumerable<double>, IEquatable<Matrix3x3>
|
internal sealed class Matrix3x3 : IEnumerable<double>, IEquatable<Matrix3x3>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The identity matrix. The result of multiplying a matrix with
|
/// The identity matrix. The result of multiplying a matrix with
|
||||||
@ -69,14 +69,14 @@ namespace UglyToad.PdfPig.Util
|
|||||||
///
|
///
|
||||||
/// If an inverse matrix does not exist, null is returned.
|
/// If an inverse matrix does not exist, null is returned.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Matrix3x3? Inverse()
|
public Matrix3x3 Inverse()
|
||||||
{
|
{
|
||||||
var determinant = GetDeterminant();
|
var determinant = GetDeterminant();
|
||||||
|
|
||||||
// No inverse matrix exists when determinant is zero
|
// No inverse matrix exists when determinant is zero
|
||||||
if (determinant == 0)
|
if (determinant == 0)
|
||||||
{
|
{
|
||||||
return null;
|
throw new InvalidOperationException("May not inverse a matrix with a determinant of 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var transposed = Transpose();
|
var transposed = Transpose();
|
||||||
@ -162,7 +162,7 @@ namespace UglyToad.PdfPig.Util
|
|||||||
public bool Equals(Matrix3x3? other)
|
public bool Equals(Matrix3x3? other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using UglyToad.PdfPig.Tokens;
|
using UglyToad.PdfPig.Tokens;
|
||||||
|
|
||||||
namespace UglyToad.PdfPig.Writer
|
namespace UglyToad.PdfPig.Writer
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
namespace UglyToad.PdfPig.Writer
|
namespace UglyToad.PdfPig.Writer
|
||||||
{
|
{
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of pdf writer to use.
|
/// Type of pdf writer to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -18,4 +14,4 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ObjectInMemoryDedup
|
ObjectInMemoryDedup
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user