Skip to content

Commit 7af7151

Browse files
Merge branch '3.0-poc' into 3.0-poc-draft
2 parents 1ef3a73 + 5e19c7f commit 7af7151

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2400
-427
lines changed

OpenMcdf3.Benchmarks/InMemory.cs

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,80 +18,78 @@ public class InMemory : IDisposable
1818
private const string storageName = "MyStorage";
1919
private const string streamName = "MyStream";
2020

21-
private byte[] _readBuffer;
21+
private byte[] readBuffer;
2222

23-
private MemoryStream _stream;
23+
private readonly MemoryStream readStream = new();
24+
private readonly MemoryStream writeStream = new();
2425

25-
[Params(Kb / 2, Kb, 4 * Kb, 128 * Kb, 256 * Kb, 512 * Kb, Kb * Kb)]
26+
[Params(512, Mb /*Kb, 4 * Kb, 128 * Kb, 256 * Kb, 512 * Kb,*/)]
2627
public int BufferSize { get; set; }
2728

2829
[Params(Mb /*, 8 * Mb, 64 * Mb, 128 * Mb*/)]
2930
public int TotalStreamSize { get; set; }
3031

3132
public void Dispose()
3233
{
33-
_stream?.Dispose();
34+
readStream?.Dispose();
35+
writeStream?.Dispose();
3436
}
3537

3638
[GlobalSetup]
3739
public void GlobalSetup()
3840
{
39-
_stream = new MemoryStream();
40-
//_stream = File.Create("D:\\test.cfb");
41-
_readBuffer = new byte[BufferSize];
41+
readBuffer = new byte[BufferSize];
4242
CreateFile(1);
4343
}
4444

45-
[GlobalCleanup]
46-
public void GlobalCleanup()
47-
{
48-
_stream.Dispose();
49-
_stream = null;
50-
_readBuffer = null;
51-
}
52-
5345
[Benchmark]
54-
public void Test()
46+
public void Read()
5547
{
56-
//
57-
_stream.Seek(0L, SeekOrigin.Begin);
58-
//
59-
using var compoundFile = RootStorage.Open(_stream);
60-
using Stream cfStream = compoundFile.OpenStream(streamName + 0);
48+
using var compoundFile = RootStorage.Open(readStream);
49+
using CfbStream cfStream = compoundFile.OpenStream(streamName + 0);
6150
long streamSize = cfStream.Length;
6251
long position = 0L;
6352
while (true)
6453
{
6554
if (position >= streamSize)
6655
break;
67-
int read = cfStream.Read(_readBuffer, 0, _readBuffer.Length);
56+
int read = cfStream.Read(readBuffer, 0, readBuffer.Length);
6857
position += read;
6958
if (read <= 0) break;
7059
}
60+
}
61+
62+
[Benchmark]
63+
public void Write()
64+
{
65+
MemoryStream memoryStream = writeStream;
66+
using var storage = RootStorage.Create(memoryStream);
67+
Storage subStorage = storage.CreateStorage(storageName);
68+
CfbStream stream = subStorage.CreateStream(streamName + 0);
7169

72-
//compoundFile.Close();
70+
while (stream.Length < TotalStreamSize)
71+
{
72+
stream.Write(readBuffer, 0, readBuffer.Length);
73+
}
7374
}
7475

7576
private void CreateFile(int streamCount)
7677
{
77-
var iterationCount = TotalStreamSize / BufferSize;
78+
int iterationCount = TotalStreamSize / BufferSize;
7879

79-
var buffer = new byte[BufferSize];
80-
Array.Fill(buffer, byte.MaxValue);
80+
byte[] buffer = new byte[BufferSize];
81+
buffer.AsSpan().Fill(byte.MaxValue);
8182
const CFSConfiguration flags = CFSConfiguration.Default | CFSConfiguration.LeaveOpen;
82-
using (var compoundFile = new CompoundFile(CFSVersion.Ver_3, flags))
83+
using var compoundFile = new CompoundFile(CFSVersion.Ver_3, flags);
84+
CFStorage st = compoundFile.RootStorage;
85+
for (int streamId = 0; streamId < streamCount; ++streamId)
8386
{
84-
//var st = compoundFile.RootStorage.AddStorage(storageName);
85-
var st = compoundFile.RootStorage;
86-
for (var streamId = 0; streamId < streamCount; ++streamId)
87-
{
88-
var sm = st.AddStream(streamName + streamId);
89-
90-
for (var iteration = 0; iteration < iterationCount; ++iteration) sm.Append(buffer);
91-
}
92-
93-
compoundFile.Save(_stream);
94-
compoundFile.Close();
87+
CFStream sm = st.AddStream(streamName + streamId);
88+
for (int iteration = 0; iteration < iterationCount; ++iteration)
89+
sm.Append(buffer);
9590
}
91+
92+
compoundFile.Save(readStream);
93+
compoundFile.Close();
9694
}
9795
}

OpenMcdf3.Benchmarks/OpenMcdf3.Benchmarks.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4+
<TargetFrameworks>net8.0</TargetFrameworks>
5+
<LangVersion>11.0</LangVersion>
46
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0</TargetFramework>
67
<ImplicitUsings>enable</ImplicitUsings>
78
<Nullable>enable</Nullable>
89
</PropertyGroup>

OpenMcdf3.Benchmarks/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace OpenMcdf3.Benchmarks;
44

5-
internal class Program
5+
internal static class Program
66
{
77
private static void Main(string[] args)
88
{

OpenMcdf3.Perf/OpenMcdf3.Perf.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net8.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\OpenMcdf3\OpenMcdf3.csproj" />
12+
</ItemGroup>
13+
14+
</Project>

OpenMcdf3.Perf/Program.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Diagnostics;
2+
3+
namespace OpenMcdf3.Perf;
4+
5+
internal sealed class Program
6+
{
7+
static void Main(string[] args)
8+
{
9+
var stopwatch = Stopwatch.StartNew();
10+
Write(Version.V3, 512, 1024);
11+
Console.WriteLine($"Elapsed: {stopwatch.Elapsed}");
12+
}
13+
14+
static void Write(Version version, int length, int iterations)
15+
{
16+
// Fill with bytes equal to their position modulo 256
17+
byte[] expectedBuffer = new byte[length];
18+
for (int i = 0; i < length; i++)
19+
expectedBuffer[i] = (byte)i;
20+
21+
//byte[] actualBuffer = new byte[length];
22+
23+
using MemoryStream memoryStream = new(2 * length);
24+
using var rootStorage = RootStorage.Create(memoryStream, version);
25+
using Stream stream = rootStorage.CreateStream("TestStream");
26+
27+
for (int i = 0; i < iterations; i++)
28+
{
29+
stream.Write(expectedBuffer, 0, expectedBuffer.Length);
30+
}
31+
}
32+
}

OpenMcdf3.Tests/AssemblyInfo.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Runtime.InteropServices;
2+
3+
// In SDK-style projects such as this one, several assembly attributes that were historically
4+
// defined in this file are now automatically added during build and populated with
5+
// values defined in project properties. For details of which attributes are included
6+
// and how to customise this process see: https://aka.ms/assembly-info-properties
7+
8+
9+
// Setting ComVisible to false makes the types in this assembly not visible to COM
10+
// components. If you need to access a type in this assembly from COM, set the ComVisible
11+
// attribute to true on that type.
12+
13+
[assembly: ComVisible(false)]
14+
15+
// The following GUID is for the ID of the typelib if this project is exposed to COM.
16+
17+
[assembly: Guid("38e3c8a7-44c7-4d13-9c30-7aa75b038c83")]
18+
19+
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]

OpenMcdf3.Tests/BinaryWriterTests.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
namespace OpenMcdf3.Tests;
2+
3+
[TestClass]
4+
public sealed class BinaryWriterTests
5+
{
6+
[TestMethod]
7+
public void WriteGuid()
8+
{
9+
byte[] bytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 };
10+
Guid expectedGuid = new(bytes);
11+
using MemoryStream stream = new(bytes);
12+
using (CfbBinaryWriter writer = new(stream))
13+
writer.Write(expectedGuid);
14+
15+
stream.Position = 0;
16+
using CfbBinaryReader reader = new(stream);
17+
Guid actualGuid = reader.ReadGuid();
18+
19+
Assert.AreEqual(expectedGuid, actualGuid);
20+
}
21+
22+
[TestMethod]
23+
[DataRow("TestStream_v3_0.cfs")]
24+
[DataRow("TestStream_v4_0.cfs")]
25+
public void WriteHeader(string fileName)
26+
{
27+
using FileStream stream = File.OpenRead(fileName);
28+
using CfbBinaryReader reader = new(stream);
29+
Header header = reader.ReadHeader();
30+
31+
using MemoryStream memoryStream = new();
32+
using CfbBinaryWriter writer = new(memoryStream);
33+
writer.Write(header);
34+
35+
memoryStream.Position = 0;
36+
using CfbBinaryReader reader2 = new(memoryStream);
37+
Header actualHeader = reader2.ReadHeader();
38+
39+
Assert.AreEqual(header, actualHeader);
40+
}
41+
42+
[TestMethod]
43+
public void WriteDirectoryEntry()
44+
{
45+
DirectoryEntry expected = new()
46+
{
47+
Name = "Root Entry",
48+
Type = StorageType.Storage,
49+
Color = NodeColor.Red,
50+
LeftSiblingId = 2,
51+
RightSiblingId = 3,
52+
ChildId = 4,
53+
CLSID = Guid.NewGuid(),
54+
StateBits = 5,
55+
CreationTime = DateTime.UtcNow,
56+
ModifiedTime = DateTime.UtcNow,
57+
StartSectorId = 6,
58+
StreamLength = 7
59+
};
60+
61+
using MemoryStream stream = new();
62+
using CfbBinaryWriter writer = new(stream);
63+
writer.Write(expected);
64+
65+
stream.Position = 0;
66+
using CfbBinaryReader reader = new(stream);
67+
DirectoryEntry actual = reader.ReadDirectoryEntry(Version.V4, 0);
68+
69+
Assert.AreEqual(expected, actual);
70+
}
71+
}

OpenMcdf3.Tests/DebugWriter.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System.Diagnostics;
2+
using System.Text;
3+
4+
namespace OpenMcdf3.Tests;
5+
6+
internal sealed class DebugWriter : TextWriter
7+
{
8+
public override Encoding Encoding => Encoding.Unicode;
9+
10+
public override void Write(char value) => Debug.Write(value);
11+
12+
public override void Write(string? value) => Debug.Write(value);
13+
14+
public override void WriteLine(string? value) => Debug.WriteLine(value);
15+
}

OpenMcdf3.Tests/OpenMcdf3.Tests.csproj

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net8.0</TargetFramework>
4+
<TargetFrameworks>net48;net8.0</TargetFrameworks>
55
<OutputType>Exe</OutputType>
66
<LangVersion>11.0</LangVersion>
77
<ImplicitUsings>enable</ImplicitUsings>
@@ -14,7 +14,7 @@
1414

1515
<ItemGroup>
1616
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
17-
<PackageReference Include="MSTest" Version="3.6.1" />
17+
<PackageReference Include="MSTest" Version="3.6.2" />
1818
</ItemGroup>
1919

2020
<ItemGroup>
@@ -68,6 +68,9 @@
6868
<None Update="TestStream_v3_65.cfs">
6969
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
7070
</None>
71+
<None Update="TestStream_v3_65536.cfs">
72+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
73+
</None>
7174
<None Update="TestStream_v4_0.cfs">
7275
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
7376
</None>

OpenMcdf3.Tests/StorageTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,41 @@ public void Read(string fileName, long storageCount)
1414
IEnumerable<EntryInfo> storageEntries = rootStorage.EnumerateEntries(StorageType.Storage);
1515
Assert.AreEqual(storageCount, storageEntries.Count());
1616
}
17+
18+
[TestMethod]
19+
[DataRow(Version.V3, 0)]
20+
[DataRow(Version.V3, 1)]
21+
[DataRow(Version.V3, 2)]
22+
[DataRow(Version.V3, 4)] // Required 2 sectors including root
23+
[DataRow(Version.V4, 0)]
24+
[DataRow(Version.V4, 1)]
25+
[DataRow(Version.V4, 2)]
26+
[DataRow(Version.V4, 32)] // Required 2 sectors including root
27+
public void CreateStorage(Version version, int subStorageCount)
28+
{
29+
using MemoryStream memoryStream = new();
30+
using (var rootStorage = RootStorage.Create(memoryStream, version))
31+
{
32+
for (int i = 0; i < subStorageCount; i++)
33+
rootStorage.CreateStorage($"Test{i}");
34+
}
35+
36+
memoryStream.Position = 0;
37+
using (var rootStorage = RootStorage.Open(memoryStream))
38+
{
39+
IEnumerable<EntryInfo> entries = rootStorage.EnumerateEntries();
40+
Assert.AreEqual(subStorageCount, entries.Count());
41+
}
42+
}
43+
44+
[TestMethod]
45+
[DataRow(Version.V3)]
46+
[DataRow(Version.V4)]
47+
public void CreateDuplicateStorageThrowsException(Version version)
48+
{
49+
using MemoryStream memoryStream = new();
50+
using var rootStorage = RootStorage.Create(memoryStream, version);
51+
rootStorage.CreateStorage("Test");
52+
Assert.ThrowsException<IOException>(() => rootStorage.CreateStorage("Test"));
53+
}
1754
}

0 commit comments

Comments
 (0)