Initial commit

This commit is contained in:
2026-07-13 09:25:40 +07:00
parent c08ff54676
commit bccfb156d7
1938 changed files with 641646 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2016 The Cartographer Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.IO.Compression;
using System.Text;
using System.Text.Json;
namespace CartographerSharp.IO;
/// <summary>
/// A simple writer of a compressed sequence of protocol buffer messages to a file.
/// The format is not intended to be compatible with any other format used outside of Cartographer.
/// </summary>
public class ProtoStreamWriter : IProtoStreamWriter, IDisposable
{
// First eight bytes to identify our proto stream format.
private const ulong Magic = 0x7b1d1f7b5bf501db;
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = false,
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never
};
private readonly FileStream _fileStream;
private bool _disposed;
private bool _magicWritten;
public ProtoStreamWriter(string filename)
{
if (string.IsNullOrEmpty(filename))
throw new ArgumentException("Filename cannot be null or empty", nameof(filename));
_fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
WriteMagic();
}
private void WriteMagic()
{
WriteSizeAsLittleEndian(Magic);
_magicWritten = true;
}
private void WriteSizeAsLittleEndian(ulong size)
{
for (int i = 0; i < 8; i++)
{
_fileStream.WriteByte((byte)(size & 0xff));
size >>= 8;
}
}
private void Write(string uncompressedData)
{
if (!_magicWritten)
{
WriteMagic();
}
// Compress using GZip
byte[] uncompressedBytes = Encoding.UTF8.GetBytes(uncompressedData);
byte[] compressedBytes;
using (var memoryStream = new MemoryStream())
{
using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, leaveOpen: true))
{
gzipStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
}
compressedBytes = memoryStream.ToArray();
}
// Write compressed size
WriteSizeAsLittleEndian((ulong)compressedBytes.Length);
// Write compressed data
_fileStream.Write(compressedBytes, 0, compressedBytes.Length);
}
/// <summary>
/// Serializes, compresses and writes the proto to the file.
/// </summary>
public void WriteProto<T>(T proto)
{
ArgumentNullException.ThrowIfNull(proto, nameof(proto));
// Serialize to JSON (we use System.Text.Json instead of Google.Protobuf)
string json = JsonSerializer.Serialize(proto, JsonOptions);
Write(json);
}
/// <summary>
/// This should be called to check whether writing was successful.
/// </summary>
public bool Close()
{
if (_disposed)
return false;
_fileStream.Flush();
_fileStream.Close();
_disposed = true; // Prevent Dispose() from calling Close() again (double-close would throw on Flush)
return true;
}
public void Dispose()
{
if (!_disposed)
{
Close();
_fileStream?.Dispose();
_disposed = true;
}
GC.SuppressFinalize(this);
}
}