From a8a7592dcac510891d3095ba61974072c2902e3d Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:29:32 -0800 Subject: [PATCH 01/16] Simplify string.Join calls --- MetadataExtractor/DirectoryExtensions.cs | 2 +- MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs | 2 +- .../Formats/Exif/makernotes/OlympusMakernoteDescriptor.cs | 4 ++-- .../Exif/makernotes/OlympusRawInfoMakernoteDescriptor.cs | 4 ++-- .../Formats/Exif/makernotes/PanasonicMakernoteDescriptor.cs | 2 +- MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs | 2 +- MetadataExtractor/Formats/Heif/HeifMetadataReader.cs | 2 +- MetadataExtractor/Formats/Icc/IccReader.cs | 2 +- MetadataExtractor/Formats/Iptc/IptcReader.cs | 2 +- MetadataExtractor/Formats/Iptc/Iso2022Converter.cs | 2 +- MetadataExtractor/Formats/Png/PngChunkType.cs | 2 +- MetadataExtractor/Formats/Png/PngDescriptor.cs | 4 +--- .../Formats/QuickTime/QuickTimeMetadataReader.cs | 2 +- MetadataExtractor/Formats/QuickTime/QuickTimeReader.cs | 2 +- MetadataExtractor/IO/IndexedReader.cs | 2 +- MetadataExtractor/IO/SequentialReader.cs | 2 +- MetadataExtractor/TagDescriptor.cs | 3 +-- 17 files changed, 19 insertions(+), 22 deletions(-) diff --git a/MetadataExtractor/DirectoryExtensions.cs b/MetadataExtractor/DirectoryExtensions.cs index f5be0149d..9c2a4851a 100644 --- a/MetadataExtractor/DirectoryExtensions.cs +++ b/MetadataExtractor/DirectoryExtensions.cs @@ -929,7 +929,7 @@ public static bool TryGetRational(this Directory directory, int tagType, out Rat { var bytes = directory.GetByteArray(tagType); return bytes is null ? null - : encoding.GetString(bytes, 0, bytes.Length); + : encoding.GetString(bytes); } public static StringValue GetStringValue(this Directory directory, int tagType) diff --git a/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs b/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs index e35da0c27..64650f58c 100644 --- a/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs +++ b/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs @@ -173,7 +173,7 @@ public abstract class ExifDescriptorBase(T directory) try { // Decode the Unicode string and trim the Unicode zero "\0" from the end. - return Encoding.Unicode.GetString(bytes, 0, bytes.Length).TrimEnd('\0'); + return Encoding.Unicode.GetString(bytes).TrimEnd('\0'); } catch { diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusMakernoteDescriptor.cs index 49ca342c1..3c3f5b7f6 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusMakernoteDescriptor.cs @@ -471,7 +471,7 @@ public sealed class OlympusMakernoteDescriptor(OlympusMakernoteDirectory directo if (Directory.GetObject(OlympusMakernoteDirectory.TagColourMatrix) is not short[] values) return null; - return string.Join(" ", values.Select(b => b.ToString()).ToArray()); + return string.Join(" ", values); } public string? GetWbModeDescription() @@ -574,7 +574,7 @@ public sealed class OlympusMakernoteDescriptor(OlympusMakernoteDirectory directo if (bytes is null) return null; - return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + return Encoding.UTF8.GetString(bytes); } public string? GetOneTouchWbDescription() diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusRawInfoMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusRawInfoMakernoteDescriptor.cs index 2537f6c05..5d4cbe8e2 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusRawInfoMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusRawInfoMakernoteDescriptor.cs @@ -32,7 +32,7 @@ public sealed class OlympusRawInfoMakernoteDescriptor(OlympusRawInfoMakernoteDir if (Directory.GetObject(OlympusRawInfoMakernoteDirectory.TagColorMatrix2) is not short[] values) return null; - return string.Join(" ", values.Select(b => b.ToString()).ToArray()); + return string.Join(" ", values); } public string? GetYCbCrCoefficientsDescription() @@ -46,7 +46,7 @@ public sealed class OlympusRawInfoMakernoteDescriptor(OlympusRawInfoMakernoteDir ret[i] = new Rational(values[2 * i], values[2 * i + 1]); } - return string.Join(" ", ret.Select(r => r.ToDecimal().ToString()).ToArray()); + return string.Join(" ", ret.Select(r => r.ToDecimal())); } public string? GetOlympusLightSourceDescription() diff --git a/MetadataExtractor/Formats/Exif/makernotes/PanasonicMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/PanasonicMakernoteDescriptor.cs index c3af31649..5bfe18c24 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/PanasonicMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/PanasonicMakernoteDescriptor.cs @@ -255,7 +255,7 @@ public sealed class PanasonicMakernoteDescriptor(PanasonicMakernoteDirectory dir if (bytes is null) return null; - return string.Join(".", bytes.Select(b => b.ToString()).ToArray()); + return string.Join(".", bytes); } public string? GetIntelligentDRangeDescription() diff --git a/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs b/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs index 1721a3880..6e41763bc 100644 --- a/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs +++ b/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs @@ -15,7 +15,7 @@ public class HeicImagePropertyDescriptor(HeicImagePropertiesDirectory directory) return Directory.GetString(tagType) + " degrees"; case HeicImagePropertiesDirectory.TagPixelDepths: var o = Directory.GetObject(HeicImagePropertiesDirectory.TagPixelDepths); - return o is null ? null : string.Join(" ", ((byte[])o).Select(i => i.ToString()).ToArray()); + return o is null ? null : string.Join(" ", ((byte[])o).Select(i => i.ToString())); case HeicImagePropertiesDirectory.TagColorFormat: return TypeStringConverter.ToTypeString(Directory.GetUInt32(HeicImagePropertiesDirectory.TagColorFormat)); case HeicImagePropertiesDirectory.TagColorPrimaries: diff --git a/MetadataExtractor/Formats/Heif/HeifMetadataReader.cs b/MetadataExtractor/Formats/Heif/HeifMetadataReader.cs index 8a79feb9f..098bbb68c 100644 --- a/MetadataExtractor/Formats/Heif/HeifMetadataReader.cs +++ b/MetadataExtractor/Formats/Heif/HeifMetadataReader.cs @@ -66,7 +66,7 @@ void ParseQuickTimeTest() { dir.Set( QuickTimeFileTypeDirectory.TagCompatibleBrands, - string.Join(", ", ftype.CompatibleBrandStrings.ToArray())); + string.Join(", ", ftype.CompatibleBrandStrings)); } directories.Add(dir); diff --git a/MetadataExtractor/Formats/Icc/IccReader.cs b/MetadataExtractor/Formats/Icc/IccReader.cs index 58c3a0fd3..5632a326e 100644 --- a/MetadataExtractor/Formats/Icc/IccReader.cs +++ b/MetadataExtractor/Formats/Icc/IccReader.cs @@ -162,7 +162,7 @@ public static string GetStringFromUInt32(uint d) unchecked((byte)d) }; - return Encoding.UTF8.GetString(b, 0, b.Length); + return Encoding.UTF8.GetString(b); } } } diff --git a/MetadataExtractor/Formats/Iptc/IptcReader.cs b/MetadataExtractor/Formats/Iptc/IptcReader.cs index fb2872cdb..af85e6a0e 100644 --- a/MetadataExtractor/Formats/Iptc/IptcReader.cs +++ b/MetadataExtractor/Formats/Iptc/IptcReader.cs @@ -150,7 +150,7 @@ private static void ProcessTag(SequentialReader reader, Directory directory, int if (charset is null) { // Unable to determine the charset, so fall through and treat tag as a regular string - charset = Encoding.UTF8.GetString(bytes, 0, bytes.Length); + charset = Encoding.UTF8.GetString(bytes); } directory.Set(tagIdentifier, charset); return; diff --git a/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs b/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs index 0f3bcfaa0..33f12ecce 100644 --- a/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs +++ b/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs @@ -91,7 +91,7 @@ public static class Iso2022Converter { try { - var s = encoding.GetString(bytes, 0, bytes.Length); + var s = encoding.GetString(bytes); if (s.IndexOf((char)65533) != -1) continue; return encoding; diff --git a/MetadataExtractor/Formats/Png/PngChunkType.cs b/MetadataExtractor/Formats/Png/PngChunkType.cs index 6b159c26f..3e423b697 100644 --- a/MetadataExtractor/Formats/Png/PngChunkType.cs +++ b/MetadataExtractor/Formats/Png/PngChunkType.cs @@ -146,7 +146,7 @@ private static void ValidateBytes(byte[] bytes) private static bool IsValidByte(byte b) => b is >= 65 and <= 90 or >= 97 and <= 122; - public string Identifier => Encoding.UTF8.GetString(_bytes, 0, _bytes.Length); + public string Identifier => Encoding.UTF8.GetString(_bytes); public override string ToString() => Identifier; diff --git a/MetadataExtractor/Formats/Png/PngDescriptor.cs b/MetadataExtractor/Formats/Png/PngDescriptor.cs index e1118878d..1f019323e 100644 --- a/MetadataExtractor/Formats/Png/PngDescriptor.cs +++ b/MetadataExtractor/Formats/Png/PngDescriptor.cs @@ -73,9 +73,7 @@ public sealed class PngDescriptor(PngDirectory directory) { return Directory.GetObject(PngDirectory.TagTextualData) is not IList pairs ? null - : string.Join( - "\n", - pairs.Select(kv => $"{kv.Key}: {kv.Value}")); + : string.Join("\n", pairs.Select(kv => $"{kv.Key}: {kv.Value}")); } public string? GetBackgroundColorDescription() diff --git a/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs b/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs index 150213fa5..dabce333c 100644 --- a/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs +++ b/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs @@ -296,7 +296,7 @@ void MoovHandler(AtomCallbackArgs a) a.Reader.Skip(4L); var partId = a.Reader.GetUInt32(); var featureCode = a.Reader.GetUInt32(); - var featureValue = string.Join(" ", a.Reader.GetBytes(4).Select(v => v.ToString("X2")).ToArray()); + var featureValue = string.Join(" ", a.Reader.GetBytes(4).Select(v => v.ToString("X2"))); Debug.WriteLine($"PartId={partId} FeatureCode={featureCode} FeatureValue={featureValue}"); break; } diff --git a/MetadataExtractor/Formats/QuickTime/QuickTimeReader.cs b/MetadataExtractor/Formats/QuickTime/QuickTimeReader.cs index cd8aa92f5..07eb7a055 100644 --- a/MetadataExtractor/Formats/QuickTime/QuickTimeReader.cs +++ b/MetadataExtractor/Formats/QuickTime/QuickTimeReader.cs @@ -50,7 +50,7 @@ public string TypeString var bytes = BitConverter.GetBytes(Type); Array.Reverse(bytes); #if NETSTANDARD1_3 - return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + return Encoding.UTF8.GetString(bytes); #else return Encoding.ASCII.GetString(bytes); #endif diff --git a/MetadataExtractor/IO/IndexedReader.cs b/MetadataExtractor/IO/IndexedReader.cs index 16a9b2237..36cf5d962 100644 --- a/MetadataExtractor/IO/IndexedReader.cs +++ b/MetadataExtractor/IO/IndexedReader.cs @@ -346,7 +346,7 @@ public string GetNullTerminatedString(int index, int maxLengthBytes, Encoding? e { var bytes = GetNullTerminatedBytes(index, maxLengthBytes); - return (encoding ?? Encoding.UTF8).GetString(bytes, 0, bytes.Length); + return (encoding ?? Encoding.UTF8).GetString(bytes); } /// diff --git a/MetadataExtractor/IO/SequentialReader.cs b/MetadataExtractor/IO/SequentialReader.cs index 97f82b746..69e6557ed 100644 --- a/MetadataExtractor/IO/SequentialReader.cs +++ b/MetadataExtractor/IO/SequentialReader.cs @@ -255,7 +255,7 @@ public string GetNullTerminatedString(int maxLengthBytes, Encoding? encoding = n { var bytes = GetNullTerminatedBytes(maxLengthBytes, moveToMaxLength); - return (encoding ?? Encoding.UTF8).GetString(bytes, 0, bytes.Length); + return (encoding ?? Encoding.UTF8).GetString(bytes); } /// diff --git a/MetadataExtractor/TagDescriptor.cs b/MetadataExtractor/TagDescriptor.cs index 48ba39ac6..1bd7ac57c 100644 --- a/MetadataExtractor/TagDescriptor.cs +++ b/MetadataExtractor/TagDescriptor.cs @@ -221,8 +221,7 @@ public TagDescriptor(T directory) try { - return Encoding.UTF8 - .GetString(values, 0, values.Length) + return Encoding.UTF8.GetString(values) .Trim('\0', ' ', '\r', '\n', '\t'); } catch From 99e3faebeaf2c821fe725dbe078d3caf3d01bcf5 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:29:44 -0800 Subject: [PATCH 02/16] Fix formatting --- .../Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs | 2 +- MetadataExtractor/Formats/Iso14496/TypeStringConverter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs index 582e4ba82..2fbd46e29 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs @@ -109,7 +109,7 @@ public sealed class OlympusFocusInfoMakernoteDescriptor(OlympusFocusInfoMakernot if (values.Length == 0) return null; - var join = $"{values[0]}" + (values.Length > 1 ? $"{ values[1]}" : ""); + var join = $"{values[0]}" + (values.Length > 1 ? $"{values[1]}" : ""); return join switch { diff --git a/MetadataExtractor/Formats/Iso14496/TypeStringConverter.cs b/MetadataExtractor/Formats/Iso14496/TypeStringConverter.cs index cefae5e48..8bdd417ca 100644 --- a/MetadataExtractor/Formats/Iso14496/TypeStringConverter.cs +++ b/MetadataExtractor/Formats/Iso14496/TypeStringConverter.cs @@ -26,7 +26,7 @@ public static uint ToTypeId(string typeString) (((typeString[0] & 0xFF) << 24) | ((typeString[1] & 0xFF) << 16) | ((typeString[2] & 0xFF) << 8) | - ( typeString[3] & 0xFF)); + (typeString[3] & 0xFF)); } } } From 03a8a061c7a45d75d856815820fb5a8d96c69ee5 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:29:56 -0800 Subject: [PATCH 03/16] Use new GetString polyfill --- MetadataExtractor/Formats/Riff/RiffReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/Riff/RiffReader.cs b/MetadataExtractor/Formats/Riff/RiffReader.cs index 5ddedfb5a..fe7406dd1 100644 --- a/MetadataExtractor/Formats/Riff/RiffReader.cs +++ b/MetadataExtractor/Formats/Riff/RiffReader.cs @@ -31,7 +31,7 @@ public void ProcessRiff(SequentialReader reader, IRiffHandler handler) Span fileFourCc = stackalloc byte[4]; reader.GetBytes(fileFourCc); if (!fileFourCc.SequenceEqual("RIFF"u8)) - throw new RiffProcessingException("Invalid RIFF header: " + Encoding.ASCII.GetString(fileFourCc.ToArray())); + throw new RiffProcessingException("Invalid RIFF header: " + Encoding.ASCII.GetString(fileFourCc)); // The total size of the chunks that follow plus 4 bytes for the 'WEBP' or 'AVI ' FourCC int fileSize = reader.GetInt32(); From 731ada762392d63d2568580e444df85e36cb625e Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:31:17 -0800 Subject: [PATCH 04/16] Remove Empty class --- MetadataExtractor/Formats/Wav/WavFormatDescriptor.cs | 2 +- MetadataExtractor/IO/IndexedReader.cs | 2 +- MetadataExtractor/IO/SequentialReader.cs | 2 +- MetadataExtractor/Util/Empty.cs | 8 -------- 4 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 MetadataExtractor/Util/Empty.cs diff --git a/MetadataExtractor/Formats/Wav/WavFormatDescriptor.cs b/MetadataExtractor/Formats/Wav/WavFormatDescriptor.cs index 04dd98871..0eb11f12d 100644 --- a/MetadataExtractor/Formats/Wav/WavFormatDescriptor.cs +++ b/MetadataExtractor/Formats/Wav/WavFormatDescriptor.cs @@ -14,7 +14,7 @@ public sealed class WavFormatDescriptor(WavFormatDirectory directory) : TagDescr TagFormat => GetFormatDescription(), TagSamplesPerSec => Directory.GetUInt32(tag).ToString("0 bps"), TagBytesPerSec => Directory.GetUInt32(tag).ToString("0 bps"), - TagSubformat => BitConverter.ToString(Directory.GetByteArray(tag) ?? Empty.ByteArray).Replace("-", ""), + TagSubformat => BitConverter.ToString(Directory.GetByteArray(tag) ?? []).Replace("-", ""), _ => base.GetDescription(tag), }; } diff --git a/MetadataExtractor/IO/IndexedReader.cs b/MetadataExtractor/IO/IndexedReader.cs index 36cf5d962..1ad977d2f 100644 --- a/MetadataExtractor/IO/IndexedReader.cs +++ b/MetadataExtractor/IO/IndexedReader.cs @@ -388,7 +388,7 @@ public byte[] GetNullTerminatedBytes(int index, int maxLengthBytes) length++; if (length == 0) - return Empty.ByteArray; + return []; if (length == maxLengthBytes) return buffer; diff --git a/MetadataExtractor/IO/SequentialReader.cs b/MetadataExtractor/IO/SequentialReader.cs index 69e6557ed..d16888206 100644 --- a/MetadataExtractor/IO/SequentialReader.cs +++ b/MetadataExtractor/IO/SequentialReader.cs @@ -320,7 +320,7 @@ public byte[] GetNullTerminatedBytes(int maxLengthBytes, bool moveToMaxLength = } if (length == 0) - return Empty.ByteArray; + return []; if (length == maxLengthBytes) return buffer; var bytes = new byte[length]; diff --git a/MetadataExtractor/Util/Empty.cs b/MetadataExtractor/Util/Empty.cs deleted file mode 100644 index 2a19eade9..000000000 --- a/MetadataExtractor/Util/Empty.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -namespace MetadataExtractor; - -internal static class Empty -{ - public static readonly byte[] ByteArray = []; -} From ad1e954218378d0bc19e4b5457024c9b64bb9af4 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:35:36 -0800 Subject: [PATCH 05/16] Eliminate byte[] allocation in QuickTimeMetadataReader --- .../Formats/QuickTime/QuickTimeMetadataReader.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs b/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs index dabce333c..c3a295c69 100644 --- a/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs +++ b/MetadataExtractor/Formats/QuickTime/QuickTimeMetadataReader.cs @@ -318,7 +318,9 @@ void Handler(AtomCallbackArgs a) ReadOnlySpan xmp = [0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8, 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac]; if (a.BytesLeft >= xmp.Length) { - var uuid = a.Reader.GetBytes(xmp.Length); + Span uuid = stackalloc byte[16]; // xmp length is 16 + + a.Reader.GetBytes(uuid); if (xmp.SequenceEqual(uuid)) { var xmpBytes = a.Reader.GetNullTerminatedBytes((int)a.BytesLeft); From 3fcef87edbe992cc5feee489584ddd9460550f60 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:40:53 -0800 Subject: [PATCH 06/16] Eliminate allocation in Get4ccString --- .../Formats/QuickTime/QuickTimeReaderExtensions.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs b/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs index 76eeb98ca..17f3be52e 100644 --- a/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs +++ b/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs @@ -9,12 +9,11 @@ public static class QuickTimeReaderExtensions { public static string Get4ccString(this SequentialReader reader) { - var sb = new StringBuilder(4); - sb.Append((char)reader.GetByte()); - sb.Append((char)reader.GetByte()); - sb.Append((char)reader.GetByte()); - sb.Append((char)reader.GetByte()); - return sb.ToString(); + Span bytes = stackalloc byte[4]; + + reader.GetBytes(bytes); + + return new string([(char)bytes[0], (char)bytes[1], (char)bytes[2], (char)bytes[3]]); } public static decimal Get16BitFixedPoint(this SequentialReader reader) From 1ddd6273021e86b0c2701445b0a0fe2af49c7254 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:48:25 -0800 Subject: [PATCH 07/16] Update ShouldAcceptList to accept utf8 bytes --- MetadataExtractor/Formats/Avi/AviRiffHandler.cs | 11 +++++------ MetadataExtractor/Formats/Riff/IRiffHandler.cs | 2 +- MetadataExtractor/Formats/Riff/RiffHandler.cs | 2 +- MetadataExtractor/Formats/Riff/RiffReader.cs | 2 +- MetadataExtractor/Formats/Wav/WavRiffHandler.cs | 2 +- MetadataExtractor/Formats/WebP/WebpRiffHandler.cs | 2 +- .../PublicAPI/net462/PublicAPI.Shipped.txt | 10 +++++----- .../PublicAPI/netstandard1.3/PublicAPI.Shipped.txt | 10 +++++----- .../PublicAPI/netstandard2.1/PublicAPI.Shipped.txt | 10 +++++----- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/MetadataExtractor/Formats/Avi/AviRiffHandler.cs b/MetadataExtractor/Formats/Avi/AviRiffHandler.cs index 852beb7b6..03ab69f97 100644 --- a/MetadataExtractor/Formats/Avi/AviRiffHandler.cs +++ b/MetadataExtractor/Formats/Avi/AviRiffHandler.cs @@ -39,13 +39,12 @@ public AviRiffHandler(List directories) _ => false }; - public bool ShouldAcceptList(string fourCc) => fourCc switch + public bool ShouldAcceptList(ReadOnlySpan fourCc) { - "hdrl" => true, - "strl" => true, - "AVI " => true, - _ => false - }; + return fourCc.SequenceEqual("hdrl"u8) + || fourCc.SequenceEqual("strl"u8) + || fourCc.SequenceEqual("AVI "u8); + } public void ProcessChunk(string fourCc, byte[] payload) { diff --git a/MetadataExtractor/Formats/Riff/IRiffHandler.cs b/MetadataExtractor/Formats/Riff/IRiffHandler.cs index 283a2d694..711493f42 100644 --- a/MetadataExtractor/Formats/Riff/IRiffHandler.cs +++ b/MetadataExtractor/Formats/Riff/IRiffHandler.cs @@ -33,7 +33,7 @@ public interface IRiffHandler /// /// the four character code of this chunk /// if should be called, otherwise . - bool ShouldAcceptList(string fourCc); + bool ShouldAcceptList(ReadOnlySpan fourCc); /// Perform whatever processing is necessary for the type of chunk with its payload. /// This is only called if a previous call to with the same fourCC returned . diff --git a/MetadataExtractor/Formats/Riff/RiffHandler.cs b/MetadataExtractor/Formats/Riff/RiffHandler.cs index 66ee2522f..e3ea3cef9 100644 --- a/MetadataExtractor/Formats/Riff/RiffHandler.cs +++ b/MetadataExtractor/Formats/Riff/RiffHandler.cs @@ -30,7 +30,7 @@ public void ProcessChunk(string fourCc, byte[] payload) public abstract bool ShouldAcceptRiffIdentifier(ReadOnlySpan identifier); - public abstract bool ShouldAcceptList(string fourCc); + public abstract bool ShouldAcceptList(ReadOnlySpan fourCc); public void AddError(string errorMessage) { diff --git a/MetadataExtractor/Formats/Riff/RiffReader.cs b/MetadataExtractor/Formats/Riff/RiffReader.cs index fe7406dd1..8e1ea022f 100644 --- a/MetadataExtractor/Formats/Riff/RiffReader.cs +++ b/MetadataExtractor/Formats/Riff/RiffReader.cs @@ -70,7 +70,7 @@ private static void ProcessChunks(SequentialReader reader, long maxPosition, IRi { if (chunkSize < 4) break; - string listName = reader.GetString(4, Encoding.ASCII); + ReadOnlySpan listName = reader.GetBytes(4); if (handler.ShouldAcceptList(listName)) ProcessChunks(reader, reader.Position + chunkSize - 4, handler); else diff --git a/MetadataExtractor/Formats/Wav/WavRiffHandler.cs b/MetadataExtractor/Formats/Wav/WavRiffHandler.cs index 56b1149e1..11d1d094e 100644 --- a/MetadataExtractor/Formats/Wav/WavRiffHandler.cs +++ b/MetadataExtractor/Formats/Wav/WavRiffHandler.cs @@ -30,6 +30,6 @@ public WavRiffHandler(List directories) public override bool ShouldAcceptRiffIdentifier(ReadOnlySpan identifier) => identifier.SequenceEqual("WAVE"u8); - public override bool ShouldAcceptList(string fourCc) => false; + public override bool ShouldAcceptList(ReadOnlySpan fourCc) => false; } } diff --git a/MetadataExtractor/Formats/WebP/WebpRiffHandler.cs b/MetadataExtractor/Formats/WebP/WebpRiffHandler.cs index 31bdfc277..42f259f45 100644 --- a/MetadataExtractor/Formats/WebP/WebpRiffHandler.cs +++ b/MetadataExtractor/Formats/WebP/WebpRiffHandler.cs @@ -39,7 +39,7 @@ public bool ShouldAcceptChunk(string fourCc) => fourCc == "VP8X" || fourCc == "ICCP" || fourCc == "XMP "; - public bool ShouldAcceptList(string fourCc) => false; + public bool ShouldAcceptList(ReadOnlySpan fourCc) => false; public void ProcessChunk(string fourCc, byte[] payload) { diff --git a/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt index f36b2666f..8706df28b 100644 --- a/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt @@ -5,7 +5,7 @@ abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Pr abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.IReadOnlyCollection! abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.MinSize.get -> int abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.Populate(T! directory, byte[]! payload) -> void -abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(string! fourCc) -> bool +abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.HasFollowerIfd() -> bool @@ -2387,7 +2387,7 @@ MetadataExtractor.Formats.Avi.AviRiffHandler.AddError(string! errorMessage) -> v MetadataExtractor.Formats.Avi.AviRiffHandler.AviRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor.BmpHeaderDescriptor(MetadataExtractor.Formats.Bmp.BmpHeaderDirectory! directory) -> void @@ -3699,7 +3699,7 @@ MetadataExtractor.Formats.Riff.IRiffHandler MetadataExtractor.Formats.Riff.IRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Riff.RiffChunkHandler MetadataExtractor.Formats.Riff.RiffChunkHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void @@ -3864,7 +3864,7 @@ MetadataExtractor.Formats.WebP.WebPRiffHandler MetadataExtractor.Formats.WebP.WebPRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.WebPRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Xmp.Schema @@ -4248,7 +4248,7 @@ override MetadataExtractor.Formats.Tiff.TiffDataFormat.ToString() -> string! override MetadataExtractor.Formats.Wav.WavFactDirectory.Name.get -> string! override MetadataExtractor.Formats.Wav.WavFormatDescriptor.GetDescription(int tag) -> string? override MetadataExtractor.Formats.Wav.WavFormatDirectory.Name.get -> string! -override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(string! fourCc) -> bool +override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool override MetadataExtractor.Formats.WebP.WebPDirectory.Name.get -> string! override MetadataExtractor.Formats.Xmp.XmpDirectory.Name.get -> string! diff --git a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt index 8d36dd9e4..b4590108a 100644 --- a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt @@ -5,7 +5,7 @@ abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Pr abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.IReadOnlyCollection! abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.MinSize.get -> int abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.Populate(T! directory, byte[]! payload) -> void -abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(string! fourCc) -> bool +abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.HasFollowerIfd() -> bool @@ -2387,7 +2387,7 @@ MetadataExtractor.Formats.Avi.AviRiffHandler.AddError(string! errorMessage) -> v MetadataExtractor.Formats.Avi.AviRiffHandler.AviRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor.BmpHeaderDescriptor(MetadataExtractor.Formats.Bmp.BmpHeaderDirectory! directory) -> void @@ -3697,7 +3697,7 @@ MetadataExtractor.Formats.Riff.IRiffHandler MetadataExtractor.Formats.Riff.IRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Riff.RiffChunkHandler MetadataExtractor.Formats.Riff.RiffChunkHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void @@ -3860,7 +3860,7 @@ MetadataExtractor.Formats.WebP.WebPRiffHandler MetadataExtractor.Formats.WebP.WebPRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.WebPRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Xmp.Schema @@ -4241,7 +4241,7 @@ override MetadataExtractor.Formats.Tiff.TiffDataFormat.ToString() -> string! override MetadataExtractor.Formats.Wav.WavFactDirectory.Name.get -> string! override MetadataExtractor.Formats.Wav.WavFormatDescriptor.GetDescription(int tag) -> string? override MetadataExtractor.Formats.Wav.WavFormatDirectory.Name.get -> string! -override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(string! fourCc) -> bool +override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool override MetadataExtractor.Formats.WebP.WebPDirectory.Name.get -> string! override MetadataExtractor.Formats.Xmp.XmpDirectory.Name.get -> string! diff --git a/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt index 7bd81fc0d..e525cde9c 100644 --- a/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt @@ -5,7 +5,7 @@ abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Pr abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.IReadOnlyCollection! abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.MinSize.get -> int abstract MetadataExtractor.Formats.Riff.RiffChunkHandler.Populate(T! directory, byte[]! payload) -> void -abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(string! fourCc) -> bool +abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool abstract MetadataExtractor.Formats.Riff.RiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.HasFollowerIfd() -> bool @@ -2382,7 +2382,7 @@ MetadataExtractor.Formats.Avi.AviRiffHandler.AddError(string! errorMessage) -> v MetadataExtractor.Formats.Avi.AviRiffHandler.AviRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Avi.AviRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor MetadataExtractor.Formats.Bmp.BmpHeaderDescriptor.BmpHeaderDescriptor(MetadataExtractor.Formats.Bmp.BmpHeaderDirectory! directory) -> void @@ -3694,7 +3694,7 @@ MetadataExtractor.Formats.Riff.IRiffHandler MetadataExtractor.Formats.Riff.IRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.Riff.IRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.Riff.RiffChunkHandler MetadataExtractor.Formats.Riff.RiffChunkHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void @@ -3859,7 +3859,7 @@ MetadataExtractor.Formats.WebP.WebPRiffHandler MetadataExtractor.Formats.WebP.WebPRiffHandler.AddError(string! errorMessage) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ProcessChunk(string! fourCc, byte[]! payload) -> void MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptChunk(string! fourCc) -> bool -MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(string! fourCc) -> bool +MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool MetadataExtractor.Formats.WebP.WebPRiffHandler.WebPRiffHandler(System.Collections.Generic.List! directories) -> void MetadataExtractor.Formats.Xmp.Schema @@ -4243,7 +4243,7 @@ override MetadataExtractor.Formats.Tiff.TiffDataFormat.ToString() -> string! override MetadataExtractor.Formats.Wav.WavFactDirectory.Name.get -> string! override MetadataExtractor.Formats.Wav.WavFormatDescriptor.GetDescription(int tag) -> string? override MetadataExtractor.Formats.Wav.WavFormatDirectory.Name.get -> string! -override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(string! fourCc) -> bool +override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptList(System.ReadOnlySpan fourCc) -> bool override MetadataExtractor.Formats.Wav.WavRiffHandler.ShouldAcceptRiffIdentifier(System.ReadOnlySpan identifier) -> bool override MetadataExtractor.Formats.WebP.WebPDirectory.Name.get -> string! override MetadataExtractor.Formats.Xmp.XmpDirectory.Name.get -> string! From 0443c5487dc23924523c7eb8f2bd611d0deed276 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 09:59:11 -0800 Subject: [PATCH 08/16] Update StartsWithJpegExifPreamble to accept ReadOnlySpan --- MetadataExtractor/Formats/Exif/ExifReader.cs | 2 +- MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt | 2 +- .../PublicAPI/netstandard1.3/PublicAPI.Shipped.txt | 2 +- .../PublicAPI/netstandard2.1/PublicAPI.Shipped.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MetadataExtractor/Formats/Exif/ExifReader.cs b/MetadataExtractor/Formats/Exif/ExifReader.cs index 2eec871c2..027e596be 100644 --- a/MetadataExtractor/Formats/Exif/ExifReader.cs +++ b/MetadataExtractor/Formats/Exif/ExifReader.cs @@ -15,7 +15,7 @@ public sealed class ExifReader : JpegSegmentWithPreambleMetadataReader { public static ReadOnlySpan JpegSegmentPreamble => "Exif\x0\x0"u8; - public static bool StartsWithJpegExifPreamble(byte[] bytes) => bytes.AsSpan().StartsWith(JpegSegmentPreamble); + public static bool StartsWithJpegExifPreamble(ReadOnlySpan bytes) => bytes.StartsWith(JpegSegmentPreamble); public static int JpegSegmentPreambleLength => JpegSegmentPreamble.Length; diff --git a/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt index 8706df28b..1cbba6c7b 100644 --- a/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/net462/PublicAPI.Shipped.txt @@ -4333,7 +4333,7 @@ static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(string! file static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Exif.ExifDirectoryBase.AddExifTagNames(System.Collections.Generic.Dictionary! map) -> void static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int -static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(byte[]! bytes) -> bool +static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(System.ReadOnlySpan bytes) -> bool static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(string! filePath) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Heif.HeifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! diff --git a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt index b4590108a..9ef730822 100644 --- a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt @@ -4326,7 +4326,7 @@ static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(string! file static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Exif.ExifDirectoryBase.AddExifTagNames(System.Collections.Generic.Dictionary! map) -> void static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int -static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(byte[]! bytes) -> bool +static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(System.ReadOnlySpan bytes) -> bool static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(string! filePath) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Heif.HeifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! diff --git a/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt index e525cde9c..9c2816869 100644 --- a/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt @@ -4328,7 +4328,7 @@ static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(string! file static MetadataExtractor.Formats.Eps.EpsMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Exif.ExifDirectoryBase.AddExifTagNames(System.Collections.Generic.Dictionary! map) -> void static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int -static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(byte[]! bytes) -> bool +static MetadataExtractor.Formats.Exif.ExifReader.StartsWithJpegExifPreamble(System.ReadOnlySpan bytes) -> bool static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(string! filePath) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Gif.GifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! static MetadataExtractor.Formats.Heif.HeifMetadataReader.ReadMetadata(System.IO.Stream! stream) -> System.Collections.Generic.IReadOnlyList! From 7c5a6ca09d95f4d024e09478b7a28ff2c4d04a37 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 10:14:44 -0800 Subject: [PATCH 09/16] Use switch expression --- MetadataExtractor/Formats/Gif/GifReader.cs | 35 +++++----------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/MetadataExtractor/Formats/Gif/GifReader.cs b/MetadataExtractor/Formats/Gif/GifReader.cs index 4a880212a..3b354afad 100644 --- a/MetadataExtractor/Formats/Gif/GifReader.cs +++ b/MetadataExtractor/Formats/Gif/GifReader.cs @@ -190,35 +190,14 @@ private static GifHeaderDirectory ReadGifHeader(SequentialReader reader) var blockSizeBytes = reader.GetByte(); var blockStartPos = reader.Position; - Directory? directory; - switch (extensionLabel) + Directory? directory = extensionLabel switch { - case 0x01: - { - directory = ReadPlainTextBlock(reader, blockSizeBytes); - break; - } - case 0xf9: - { - directory = ReadControlBlock(reader); - break; - } - case 0xfe: - { - directory = ReadCommentBlock(reader, blockSizeBytes); - break; - } - case 0xff: - { - directory = ReadApplicationExtensionBlock(reader, blockSizeBytes); - break; - } - default: - { - directory = new ErrorDirectory($"Unsupported GIF extension block with type 0x{extensionLabel:X2}."); - break; - } - } + 0x01 => ReadPlainTextBlock(reader, blockSizeBytes), + 0xf9 => ReadControlBlock(reader), + 0xfe => ReadCommentBlock(reader, blockSizeBytes), + 0xff => ReadApplicationExtensionBlock(reader, blockSizeBytes), + _ => new ErrorDirectory($"Unsupported GIF extension block with type 0x{extensionLabel:X2}.") + }; var skipCount = blockStartPos + blockSizeBytes - reader.Position; if (skipCount > 0) From b229f63e94a4f93b98ecb97b0749822bb4564b2f Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 10:34:29 -0800 Subject: [PATCH 10/16] Switch on integer values to avoid string allocation --- .../LeicaType5MakernoteDescriptor.cs | 15 +++---- ...lympusCameraSettingsMakernoteDescriptor.cs | 14 +++--- .../OlympusFocusInfoMakernoteDescriptor.cs | 10 ++--- ...ympusImageProcessingMakernoteDescriptor.cs | 43 +++++++++---------- 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/MetadataExtractor/Formats/Exif/makernotes/LeicaType5MakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/LeicaType5MakernoteDescriptor.cs index dea35dda5..06ce84129 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/LeicaType5MakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/LeicaType5MakernoteDescriptor.cs @@ -30,15 +30,14 @@ public class LeicaType5MakernoteDescriptor(LeicaType5MakernoteDirectory director if (Directory.GetObject(LeicaType5MakernoteDirectory.TagExposureMode) is not byte[] values || values.Length < 4) return null; - var join = $"{values[0]} {values[1]} {values[2]} {values[3]}"; - var ret = join switch + var ret = (values[0], values[1], values[2], values[3]) switch { - "0 0 0 0" => "Program AE", - "1 0 0 0" => "Aperture-priority AE", - "1 1 0 0" => "Aperture-priority AE (1)", - "2 0 0 0" => "Shutter speed priority AE", // guess - "3 0 0 0" => "Manual", - _ => "Unknown (" + join + ")", + (0, 0, 0, 0) => "Program AE", + (1, 0, 0, 0) => "Aperture-priority AE", + (1, 1, 0, 0) => "Aperture-priority AE (1)", + (2, 0, 0, 0) => "Shutter speed priority AE", // guess + (3, 0, 0, 0) => "Manual", + _ => $"Unknown ({values[0]} {values[1]} {values[2]} {values[3]})" }; return ret; } diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.cs index 472da61ae..e61711690 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.cs @@ -651,15 +651,15 @@ public sealed class OlympusCameraSettingsMakernoteDescriptor(OlympusCameraSettin if (Directory.GetObject(OlympusCameraSettingsMakernoteDirectory.TagGradation) is not short[] values || values.Length < 3) return null; - var join = $"{values[0]} {values[1]} {values[2]}"; - var ret = join switch + var ret = (values[0], values[1], values[3]) switch { - "0 0 0" => "n/a", - "-1 -1 1" => "Low Key", - "0 -1 1" => "Normal", - "1 -1 1" => "High Key", - _ => "Unknown (" + join + ")", + (0, 0, 0) => "n/a", + (-1, -1, 1) => "Low Key", + (0, -1, 1) => "Normal", + (1, -1, 1) => "High Key", + _ => $"Unknown ({values[0]} {values[1]} {values[2]})" }; + if (values.Length > 3) { if (values[3] == 0) diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs index 2fbd46e29..467e2e141 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs @@ -77,13 +77,11 @@ public sealed class OlympusFocusInfoMakernoteDescriptor(OlympusFocusInfoMakernot if (Directory.GetObject(OlympusFocusInfoMakernoteDirectory.TagExternalFlash) is not ushort[] values || values.Length < 2) return null; - var join = $"{values[0]} {values[1]}"; - - return join switch + return (values[0], values[1]) switch { - "0 0" => "Off", - "1 0" => "On", - _ => "Unknown (" + join + ")", + (0, 0) => "Off", + (1, 0) => "On", + _ => $"Unknown ({values[0]} {values[1]})" }; } diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusImageProcessingMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusImageProcessingMakernoteDescriptor.cs index 222eca555..514ee7f1e 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusImageProcessingMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusImageProcessingMakernoteDescriptor.cs @@ -130,24 +130,23 @@ public sealed class OlympusImageProcessingMakernoteDescriptor(OlympusImageProces if (Directory.GetObject(OlympusImageProcessingMakernoteDirectory.TagAspectRatio) is not byte[] values || values.Length < 2) return null; - var join = $"{values[0]} {values[1]}"; - var ret = join switch + var ret = (values[0], values[1]) switch { - "1 1" => "4:3", - "1 4" => "1:1", - "2 1" => "3:2 (RAW)", - "2 2" => "3:2", - "3 1" => "16:9 (RAW)", - "3 3" => "16:9", - "4 1" => "1:1 (RAW)", - "4 4" => "6:6", - "5 5" => "5:4", - "6 6" => "7:6", - "7 7" => "6:5", - "8 8" => "7:5", - "9 1" => "3:4 (RAW)", - "9 9" => "3:4", - _ => "Unknown (" + join + ")", + (1, 1) => "4:3", + (1, 4) => "1:1", + (2, 1) => "3:2 (RAW)", + (2, 2) => "3:2", + (3, 1) => "16:9 (RAW)", + (3, 3) => "16:9", + (4, 1) => "1:1 (RAW)", + (4, 4) => "6:6", + (5, 5) => "5:4", + (6, 6) => "7:6", + (7, 7) => "6:5", + (8, 8) => "7:5", + (9, 1) => "3:4 (RAW)", + (9, 9) => "3:4", + _ => $"Unknown ({values[0]} {values[1]})" }; return ret; } @@ -157,14 +156,12 @@ public sealed class OlympusImageProcessingMakernoteDescriptor(OlympusImageProces if (Directory.GetObject(OlympusImageProcessingMakernoteDirectory.TagKeystoneCompensation) is not byte[] values || values.Length < 2) return null; - var join = $"{values[0]} {values[1]}"; - var ret = join switch + return (values[0], values[1]) switch { - "0 0" => "Off", - "0 1" => "On", - _ => "Unknown (" + join + ")", + (0, 0) => "Off", + (0, 1) => "On", + _ => $"Unknown ({values[0]} {values[1]})" }; - return ret; } public string? GetKeystoneDirectionDescription() From 25d2fea113de9af0dc4055b0db217d7be3aa3a96 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 18:51:02 -0800 Subject: [PATCH 11/16] Use switch statement in OlympusFocusInfoMakernoteDescriptor.GetExternalFlashZoomDescription --- .../OlympusFocusInfoMakernoteDescriptor.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs index 467e2e141..a19d11b77 100644 --- a/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs +++ b/MetadataExtractor/Formats/Exif/makernotes/OlympusFocusInfoMakernoteDescriptor.cs @@ -30,7 +30,7 @@ public sealed class OlympusFocusInfoMakernoteDescriptor(OlympusFocusInfoMakernot OlympusFocusInfoMakernoteDirectory.TagMacroLed => GetMacroLedDescription(), OlympusFocusInfoMakernoteDirectory.TagSensorTemperature => GetSensorTemperatureDescription(), OlympusFocusInfoMakernoteDirectory.TagImageStabilization => GetImageStabilizationDescription(), - _ => base.GetDescription(tagType), + _ => base.GetDescription(tagType) }; } @@ -107,15 +107,13 @@ public sealed class OlympusFocusInfoMakernoteDescriptor(OlympusFocusInfoMakernot if (values.Length == 0) return null; - var join = $"{values[0]}" + (values.Length > 1 ? $"{values[1]}" : ""); - - return join switch + return (values[0], values.Length > 1 ? values[1] : -1) switch { - "0" => "Off", - "1" => "On", - "0 0" => "Off", - "1 0" => "On", - _ => "Unknown (" + join + ")", + (0, -1) => "Off", + (1, -1) => "On", + (0, 0) => "Off", + (1, 0) => "On", + _ => $"Unknown ({string.Join(" ", values)})" }; } From f8ef4c4da2c2b2649c4b2d3556ff89537b64b804 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 18:51:28 -0800 Subject: [PATCH 12/16] Use pattern matching to simplify another string.Join condition --- MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs b/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs index 6e41763bc..920a87c22 100644 --- a/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs +++ b/MetadataExtractor/Formats/Heif/HeicImagePropertyDescriptor.cs @@ -15,7 +15,7 @@ public class HeicImagePropertyDescriptor(HeicImagePropertiesDirectory directory) return Directory.GetString(tagType) + " degrees"; case HeicImagePropertiesDirectory.TagPixelDepths: var o = Directory.GetObject(HeicImagePropertiesDirectory.TagPixelDepths); - return o is null ? null : string.Join(" ", ((byte[])o).Select(i => i.ToString())); + return o is byte[] bytes ? string.Join(" ", bytes) : null; case HeicImagePropertiesDirectory.TagColorFormat: return TypeStringConverter.ToTypeString(Directory.GetUInt32(HeicImagePropertiesDirectory.TagColorFormat)); case HeicImagePropertiesDirectory.TagColorPrimaries: From 76f35fae7ce282220ad8178641621f47abd2a1d2 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 18:51:35 -0800 Subject: [PATCH 13/16] Simplify GetString call --- MetadataExtractor/Formats/Photoshop/PhotoshopDescriptor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/Photoshop/PhotoshopDescriptor.cs b/MetadataExtractor/Formats/Photoshop/PhotoshopDescriptor.cs index e0986a45a..e2674893a 100644 --- a/MetadataExtractor/Formats/Photoshop/PhotoshopDescriptor.cs +++ b/MetadataExtractor/Formats/Photoshop/PhotoshopDescriptor.cs @@ -283,7 +283,7 @@ public sealed class PhotoshopDescriptor(PhotoshopDirectory directory) return bytes is null ? null - : Encoding.UTF8.GetString(bytes, 0, bytes.Length); + : Encoding.UTF8.GetString(bytes); } private string? GetBinaryDataString(int tagType) From 48f9cba3a874561dd7f76aedbb9b35c6aa7dc2e5 Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 18:57:37 -0800 Subject: [PATCH 14/16] Use Encoding.ASCII.GetString --- .../Formats/QuickTime/QuickTimeReaderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs b/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs index 17f3be52e..4bba9909e 100644 --- a/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs +++ b/MetadataExtractor/Formats/QuickTime/QuickTimeReaderExtensions.cs @@ -13,7 +13,7 @@ public static string Get4ccString(this SequentialReader reader) reader.GetBytes(bytes); - return new string([(char)bytes[0], (char)bytes[1], (char)bytes[2], (char)bytes[3]]); + return Encoding.ASCII.GetString(bytes); } public static decimal Get16BitFixedPoint(this SequentialReader reader) From 446e295ea1c696456b328ad44efa34ffa370484c Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 19:03:49 -0800 Subject: [PATCH 15/16] Eliminate byte[] allocation in RiffReader --- MetadataExtractor/Formats/Riff/RiffReader.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MetadataExtractor/Formats/Riff/RiffReader.cs b/MetadataExtractor/Formats/Riff/RiffReader.cs index 8e1ea022f..ed2f329a8 100644 --- a/MetadataExtractor/Formats/Riff/RiffReader.cs +++ b/MetadataExtractor/Formats/Riff/RiffReader.cs @@ -57,6 +57,8 @@ private static void ProcessChunks(SequentialReader reader, long maxPosition, IRi { // Processing chunks. Each chunk is 8 bytes header (4 bytes CC code + 4 bytes length of chunk) + data of the chunk + Span listName = stackalloc byte[4]; + while (reader.Position < maxPosition - 8) { string chunkFourCc = reader.GetString(4, Encoding.ASCII); @@ -70,7 +72,7 @@ private static void ProcessChunks(SequentialReader reader, long maxPosition, IRi { if (chunkSize < 4) break; - ReadOnlySpan listName = reader.GetBytes(4); + listName = reader.GetBytes(4); if (handler.ShouldAcceptList(listName)) ProcessChunks(reader, reader.Position + chunkSize - 4, handler); else From 21f5e474cb09d15d93c9790dbe399496f45e645c Mon Sep 17 00:00:00 2001 From: Jason Nelson Date: Mon, 29 Jan 2024 19:10:39 -0800 Subject: [PATCH 16/16] Eliminate string allocation in Iso2022Converter --- MetadataExtractor/Formats/Iptc/Iso2022Converter.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs b/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs index 33f12ecce..e49d08d3a 100644 --- a/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs +++ b/MetadataExtractor/Formats/Iptc/Iso2022Converter.cs @@ -1,5 +1,7 @@ // Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +using System.Buffers; + namespace MetadataExtractor.Formats.Iptc { public static class Iso2022Converter @@ -89,10 +91,13 @@ public static class Iso2022Converter foreach (var encoding in encodings) { + char[] charBuffer = ArrayPool.Shared.Rent(encoding.GetMaxCharCount(bytes.Length)); + try { - var s = encoding.GetString(bytes); - if (s.IndexOf((char)65533) != -1) + int charCount = encoding.GetChars(bytes, 0, bytes.Length, charBuffer, 0); + + if (charBuffer.AsSpan(0, charCount).IndexOf((char)65533) != -1) continue; return encoding; } @@ -100,6 +105,10 @@ public static class Iso2022Converter { // fall through... } + finally + { + ArrayPool.Shared.Return(charBuffer); + } } // No encodings succeeded. Return null.