Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d52d836
Avoid unnecessary byte[] allocations
stephentoub Aug 19, 2022
1e5020e
Remove unnecessary use of FileStreamOptions
stephentoub Aug 19, 2022
6938c77
Clean up Dispose{Async} implementations
stephentoub Aug 19, 2022
5fa03e9
Clean up unnecessary consts
stephentoub Aug 19, 2022
8dd0ac1
Remove MemoryStream/Encoding.UTF8.GetBytes allocations, unnecessary a…
stephentoub Aug 19, 2022
5be57ad
Avoid string allocations in ReadMagicAttribute
stephentoub Aug 19, 2022
ab71e6c
Avoid allocation in WriteAsOctal
stephentoub Aug 19, 2022
df2d742
Improve handling of octal
stephentoub Aug 19, 2022
c6058bd
Avoid allocation for version string
stephentoub Aug 19, 2022
5756a8c
Removing boxing and char string allocation in GenerateExtendedAttribu…
stephentoub Aug 19, 2022
9539a4a
Fix a couple unnecessary dictionary lookups
stephentoub Aug 19, 2022
74bbc9c
Replace Enum.HasFlag usage
stephentoub Aug 19, 2022
46e0855
Remove allocations from Write{Posix}Name
stephentoub Aug 19, 2022
02ca7da
Replace ArrayPool use with string.Create
stephentoub Aug 19, 2022
f9eb99f
Replace more superfluous ArrayPool usage
stephentoub Aug 19, 2022
add6179
Remove ArrayPool use from System.IO.Compression.ZipFile
stephentoub Aug 20, 2022
6f8cb75
Fix inverted condition
stephentoub Aug 20, 2022
827a588
Use generic math to parse octal
stephentoub Aug 20, 2022
ae21478
Remove allocations from StringReader and string.Split
stephentoub Aug 20, 2022
d6b6727
Remove magic string allocation for Ustar when not V7
stephentoub Aug 20, 2022
480af5c
Remove file name and directory name allocation in GenerateExtendedAtt…
stephentoub Aug 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use generic math to parse octal
  • Loading branch information
stephentoub committed Aug 20, 2022
commit 827a5882f2bc36b54f7177eaee445b5bbf998ae2
Original file line number Diff line number Diff line change
Expand Up @@ -357,14 +357,14 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca
{
return null;
}
int checksum = TarHelpers.ParseOctalAsInt32(spanChecksum);
int checksum = (int)TarHelpers.ParseOctal<uint>(spanChecksum);
// Zero checksum means the whole header is empty
if (checksum == 0)
{
return null;
}

long size = TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.Size, FieldLengths.Size));
long size = (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.Size, FieldLengths.Size));
if (size < 0)
{
throw new FormatException(string.Format(SR.TarSizeFieldNegative));
Expand All @@ -373,14 +373,14 @@ private async Task ProcessDataBlockAsync(Stream archiveStream, bool copyData, Ca
// Continue with the rest of the fields that require no special checks
TarHeader header = new(initialFormat,
name: TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.Name, FieldLengths.Name)),
mode: TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.Mode, FieldLengths.Mode)),
mTime: TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(TarHelpers.ParseOctalAsInt64(buffer.Slice(FieldLocations.MTime, FieldLengths.MTime))),
mode: (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.Mode, FieldLengths.Mode)),
mTime: TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch((long)TarHelpers.ParseOctal<ulong>(buffer.Slice(FieldLocations.MTime, FieldLengths.MTime))),
typeFlag: (TarEntryType)buffer[FieldLocations.TypeFlag])
{
_checksum = checksum,
_size = size,
_uid = TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.Uid, FieldLengths.Uid)),
_gid = TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.Gid, FieldLengths.Gid)),
_uid = (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.Uid, FieldLengths.Uid)),
_gid = (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.Gid, FieldLengths.Gid)),
_linkName = TarHelpers.GetTrimmedUtf8String(buffer.Slice(FieldLocations.LinkName, FieldLengths.LinkName))
};

Expand Down Expand Up @@ -491,10 +491,10 @@ private void ReadPosixAndGnuSharedAttributes(Span<byte> buffer)
if (_typeFlag is TarEntryType.CharacterDevice or TarEntryType.BlockDevice)
{
// Major number for a character device or block device entry.
_devMajor = TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.DevMajor, FieldLengths.DevMajor));
_devMajor = (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.DevMajor, FieldLengths.DevMajor));

// Minor number for a character device or block device entry.
_devMinor = TarHelpers.ParseOctalAsInt32(buffer.Slice(FieldLocations.DevMinor, FieldLengths.DevMinor));
_devMinor = (int)TarHelpers.ParseOctal<uint>(buffer.Slice(FieldLocations.DevMinor, FieldLengths.DevMinor));
}
}

Expand All @@ -503,10 +503,10 @@ private void ReadPosixAndGnuSharedAttributes(Span<byte> buffer)
private void ReadGnuAttributes(Span<byte> buffer)
{
// Convert byte arrays
long aTime = TarHelpers.ParseOctalAsInt64(buffer.Slice(FieldLocations.ATime, FieldLengths.ATime));
long aTime = (long)TarHelpers.ParseOctal<ulong>(buffer.Slice(FieldLocations.ATime, FieldLengths.ATime));
_aTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(aTime);

long cTime = TarHelpers.ParseOctalAsInt64(buffer.Slice(FieldLocations.CTime, FieldLengths.CTime));
long cTime = (long)TarHelpers.ParseOctal<ulong>(buffer.Slice(FieldLocations.CTime, FieldLengths.CTime));
_cTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(cTime);

// TODO: Read the bytes of the currently unsupported GNU fields, in case user wants to write this entry into another GNU archive, they need to be preserved. https://github.com/dotnet/runtime/issues/68230
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Numerics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -198,13 +199,13 @@ internal static TarEntryType GetCorrectTypeFlagForFormat(TarEntryFormat format,
return entryType;
}

// Receives a byte array that represents an ASCII string containing a number in octal base.
// Converts the array to an octal base number, then transforms it to ten base and returns it.
internal static int ParseOctalAsInt32(ReadOnlySpan<byte> buffer)
/// <summary>Parses a byte span that represents an ASCII string containing a number in octal base.</summary>
internal static T ParseOctal<T>(ReadOnlySpan<byte> buffer) where T : struct, INumber<T>
{
buffer = TrimEndingNullsAndSpaces(buffer);

uint value = 0;
T octalFactor = T.CreateTruncating(8u);
T value = T.Zero;
foreach (byte b in buffer)
{
uint digit = (uint)(b - '0');
Expand All @@ -213,31 +214,10 @@ internal static int ParseOctalAsInt32(ReadOnlySpan<byte> buffer)
ThrowInvalidNumber();
}

value = checked((value * 8u) + digit);
value = checked((value * octalFactor) + T.CreateTruncating(digit));
}

return (int)value;
}

// Receives a byte array that represents an ASCII string containing a number in octal base.
// Converts the array to an octal base number, then transforms it to ten base and returns it.
internal static long ParseOctalAsInt64(ReadOnlySpan<byte> buffer)
{
buffer = TrimEndingNullsAndSpaces(buffer);

ulong value = 0;
foreach (byte b in buffer)
{
ulong digit = (ulong)(b - '0');
if (digit >= 8)
{
ThrowInvalidNumber();
}

value = checked((value * 8u) + digit);
}

return (long)value;
return value;
}

[DoesNotReturn]
Expand Down