Add .NET 8.0 C# port of OpenV2G EXI codec
- Port core EXI encoding/decoding functionality to C# - Implement V2G protocol parsing and analysis - Add simplified decoder/encoder for roundtrip testing - Create comprehensive error handling with EXI exceptions - Support both byte array and file stream operations - Include packet structure analysis for V2GTP data - Successfully builds and runs basic functionality tests 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
198
csharp/dotnet/EXI/ByteStream.cs
Normal file
198
csharp/dotnet/EXI/ByteStream.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2007-2024 C# Port
|
||||
* Original Copyright (C) 2007-2018 Siemens AG
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace V2GDecoderNet.EXI
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte Stream utilities for file operations
|
||||
/// </summary>
|
||||
public static class ByteStream
|
||||
{
|
||||
/// <summary>
|
||||
/// Write bytes to file
|
||||
/// </summary>
|
||||
/// <param name="data">byte array</param>
|
||||
/// <param name="filename">File name</param>
|
||||
/// <returns>Error-Code != 0 on failure</returns>
|
||||
public static int WriteBytesToFile(byte[] data, string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (data == null)
|
||||
return EXIErrorCodes.EXI_ERROR_OUT_OF_BYTE_BUFFER;
|
||||
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
return EXIErrorCodes.EXI_ERROR_OUTPUT_FILE;
|
||||
|
||||
File.WriteAllBytes(filename, data);
|
||||
return 0; // Success
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_OUTPUT_FILE;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_OUTPUT_FILE;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_OUTPUT_FILE;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_OUTPUT_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read bytes from file
|
||||
/// </summary>
|
||||
/// <param name="filename">File name</param>
|
||||
/// <param name="data">Output byte array</param>
|
||||
/// <param name="bytesRead">Number of bytes actually read</param>
|
||||
/// <returns>Error-Code != 0 on failure</returns>
|
||||
public static int ReadBytesFromFile(string filename, out byte[] data, out int bytesRead)
|
||||
{
|
||||
data = Array.Empty<byte>();
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
|
||||
if (!File.Exists(filename))
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
|
||||
data = File.ReadAllBytes(filename);
|
||||
bytesRead = data.Length;
|
||||
return 0; // Success
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read bytes from file with buffer size limit
|
||||
/// </summary>
|
||||
/// <param name="filename">File name</param>
|
||||
/// <param name="maxSize">Maximum buffer size</param>
|
||||
/// <param name="data">Output byte array</param>
|
||||
/// <param name="bytesRead">Number of bytes actually read</param>
|
||||
/// <returns>Error-Code != 0 on failure</returns>
|
||||
public static int ReadBytesFromFile(string filename, int maxSize, out byte[] data, out int bytesRead)
|
||||
{
|
||||
data = Array.Empty<byte>();
|
||||
bytesRead = 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
|
||||
if (!File.Exists(filename))
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
|
||||
using var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||
var fileSize = (int)fileStream.Length;
|
||||
|
||||
if (fileSize > maxSize)
|
||||
return EXIErrorCodes.EXI_ERROR_OUT_OF_BYTE_BUFFER;
|
||||
|
||||
data = new byte[fileSize];
|
||||
bytesRead = fileStream.Read(data, 0, fileSize);
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return EXIErrorCodes.EXI_ERROR_INPUT_FILE_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert hex string to byte array
|
||||
/// </summary>
|
||||
/// <param name="hex">Hex string</param>
|
||||
/// <returns>Byte array</returns>
|
||||
public static byte[] HexStringToByteArray(string hex)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hex))
|
||||
return Array.Empty<byte>();
|
||||
|
||||
// Remove any whitespace or separators
|
||||
hex = hex.Replace(" ", "").Replace("-", "").Replace(":", "");
|
||||
|
||||
if (hex.Length % 2 != 0)
|
||||
throw new ArgumentException("Hex string must have even number of characters");
|
||||
|
||||
var result = new byte[hex.Length / 2];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
if (!byte.TryParse(hex.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, null, out result[i]))
|
||||
throw new ArgumentException($"Invalid hex characters at position {i * 2}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert byte array to hex string
|
||||
/// </summary>
|
||||
/// <param name="data">Byte array</param>
|
||||
/// <param name="uppercase">Use uppercase hex digits</param>
|
||||
/// <returns>Hex string</returns>
|
||||
public static string ByteArrayToHexString(byte[] data, bool uppercase = true)
|
||||
{
|
||||
if (data == null || data.Length == 0)
|
||||
return string.Empty;
|
||||
|
||||
var format = uppercase ? "X2" : "x2";
|
||||
return string.Concat(data.Select(b => b.ToString(format)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user