Initial commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using CeresSharp.Exceptions;
|
||||
|
||||
namespace CeresSharp.Native;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for native interop operations.
|
||||
/// Provides utilities for error handling, StringBuilder management, and common patterns.
|
||||
/// </summary>
|
||||
internal static class NativeHelpers
|
||||
{
|
||||
private const int DefaultErrorMessageCapacity = 256;
|
||||
|
||||
// Thread-local buffer pool to avoid allocating a new StringBuilder every call
|
||||
[ThreadStatic]
|
||||
private static StringBuilder? t_errorMessageBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reusable StringBuilder for error messages.
|
||||
/// Uses thread-local storage to avoid allocation on each native call.
|
||||
/// </summary>
|
||||
internal static StringBuilder CreateErrorMessageBuffer(int capacity = DefaultErrorMessageCapacity)
|
||||
{
|
||||
var sb = t_errorMessageBuffer;
|
||||
if (sb != null && sb.Capacity >= capacity)
|
||||
{
|
||||
sb.Clear();
|
||||
return sb;
|
||||
}
|
||||
sb = new StringBuilder(capacity);
|
||||
t_errorMessageBuffer = sb;
|
||||
return sb;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts error message from StringBuilder, returning null if empty.
|
||||
/// </summary>
|
||||
internal static string? ExtractErrorMessage(StringBuilder sb)
|
||||
{
|
||||
return sb.Length > 0 ? sb.ToString() : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks error code and throws exception if not successful.
|
||||
/// </summary>
|
||||
/// <param name="errorCode">The error code to check.</param>
|
||||
/// <param name="errorMessage">Optional error message. If null, will be retrieved from native code.</param>
|
||||
/// <exception cref="CeresException">Thrown when error code is not Success.</exception>
|
||||
internal static void CheckError(CeresErrorCode errorCode, string? errorMessage = null)
|
||||
{
|
||||
if (errorCode != CeresErrorCode.Success)
|
||||
{
|
||||
if (errorMessage == null)
|
||||
{
|
||||
var errorMessagePtr = CeresNative.ceres_wrapper_get_error_message(errorCode);
|
||||
errorMessage = errorMessagePtr != IntPtr.Zero
|
||||
? System.Runtime.InteropServices.Marshal.PtrToStringAnsi(errorMessagePtr)
|
||||
: $"Unknown error code: {errorCode}";
|
||||
}
|
||||
throw new CeresException(errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a native operation with error handling.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation that returns an error code.</param>
|
||||
/// <param name="errorMessageBuffer">Optional StringBuilder for error messages.</param>
|
||||
/// <exception cref="CeresException">Thrown when the operation fails.</exception>
|
||||
internal static void ExecuteWithErrorHandling(
|
||||
Func<StringBuilder, CeresErrorCode> operation,
|
||||
StringBuilder? errorMessageBuffer = null)
|
||||
{
|
||||
errorMessageBuffer ??= CreateErrorMessageBuffer();
|
||||
var errorCode = operation(errorMessageBuffer);
|
||||
if (errorCode != CeresErrorCode.Success)
|
||||
{
|
||||
var errorMessage = ExtractErrorMessage(errorMessageBuffer);
|
||||
throw new CeresException(errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user