/* * Copyright 2019 by its authors. See 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. */ #pragma warning disable 1591 using System; using System.Runtime.InteropServices; using System.ComponentModel; using System.Diagnostics.Contracts; namespace Eina { /// /// A Generic buffer designed to be a mutable string. /// Since EFL 1.23. /// public class Binbuf : IDisposable { [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_binbuf_new(); [DllImport(efl.Libs.Eina)] internal static extern void eina_binbuf_free(IntPtr buf); [DllImport(efl.Libs.Eina)] internal static extern void eina_binbuf_reset(IntPtr buf); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_append_length(IntPtr buf, byte[] str, UIntPtr length); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_append_slice(IntPtr buf, Eina.Slice slice); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_append_buffer(IntPtr buf, IntPtr data); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_append_char(IntPtr buf, byte c); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_insert_length(IntPtr buf, byte[] str, UIntPtr length, UIntPtr pos); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_insert_slice(IntPtr buf, Eina.Slice slice, UIntPtr pos); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_insert_char(IntPtr buf, byte c, UIntPtr pos); [DllImport(efl.Libs.Eina)] internal static extern byte eina_binbuf_remove(IntPtr buf, UIntPtr start, UIntPtr end); [DllImport(efl.Libs.Eina)] internal static extern IntPtr eina_binbuf_string_get(IntPtr buf); [DllImport(efl.Libs.Eina)] internal static extern void eina_binbuf_string_free(IntPtr buf); [DllImport(efl.Libs.Eina)] internal static extern UIntPtr eina_binbuf_length_get(IntPtr buf); [DllImport(efl.Libs.Eina)] internal static extern Eina.Slice eina_binbuf_slice_get(IntPtr buf); /// Pointer to the native buffer. [EditorBrowsable(EditorBrowsableState.Never)] public IntPtr Handle {get;set;} = IntPtr.Zero; /// Whether this wrapper owns the native buffer. /// Since EFL 1.23. /// public bool Own {get;set;} /// Length of the buffer. /// Since EFL 1.23. /// public int Length { get { return (int)GetLength(); } } private void InitNew() { Handle = eina_binbuf_new(); Own = true; if (Handle == IntPtr.Zero) { throw new SEHException("Could not alloc binbuf"); } } /// /// Create a new buffer. /// Since EFL 1.23. /// public Binbuf() { InitNew(); } /// /// Create a new buffer. /// Since EFL 1.23. /// public Binbuf(byte[] str, uint? length = null) { InitNew(); if (str != null) { if (!Append(str, (length != null ? length.Value : (uint)(str.Length)))) { Dispose(); throw new SEHException("Could not append on binbuf"); } } } /// /// Create a new buffer with elements. /// /// Since EFL 1.23. /// Elements to initialize the new buffer. public Binbuf(Binbuf bb) { InitNew(); if (bb != null) { Append(bb); } } /// /// Create a new buffer. /// /// The native handle to be wrapped. /// Whether this wrapper owns the native handle. [EditorBrowsable(EditorBrowsableState.Never)] public Binbuf(IntPtr handle, bool own) { Handle = handle; Own = own; } ~Binbuf() { Dispose(false); } /// Disposes of this wrapper, releasing the native buffer if owned. /// Since EFL 1.23. /// /// True if this was called from /// public method. False if /// called from the C# finalizer. protected virtual void Dispose(bool disposing) { IntPtr h = Handle; Handle = IntPtr.Zero; if (Own && h != IntPtr.Zero) { if (disposing) { eina_binbuf_free(Handle); } else { Efl.Eo.Globals.ThreadSafeFreeCbExec(eina_binbuf_free, Handle); } } } /// Releases the native resources held by this instance. /// Since EFL 1.23. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// Releases the native resources held by this instance. /// Since EFL 1.23. /// public void Free() { Dispose(); } /// /// Releases the native buffer. /// Since EFL 1.23. /// /// The native buffer. public IntPtr Release() { IntPtr h = Handle; Handle = IntPtr.Zero; return h; } /// /// Resets the buffer. /// Since EFL 1.23. /// public void Reset() { eina_binbuf_reset(Handle); } /// /// Appends a string of inputed buffer's length to the buffer, /// reallocating as necessary. /// Since EFL 1.23. /// /// The string buffer. /// true on success, false if data could not be appended. public bool Append(byte[] str) { Contract.Requires(str != null, nameof(str)); return 0 != eina_binbuf_append_length(Handle, str, (UIntPtr)(str.Length)); } /// /// Appends a string of exact length to the buffer, reallocating /// as necessary. /// Since EFL 1.23. /// /// The string buffer. /// The exact length to use. /// true on success, false if data could not be appended. public bool Append(byte[] str, uint length) { return 0 != eina_binbuf_append_length(Handle, str, (UIntPtr)length); } /// /// Appends a Binbuf to the buffer. /// Since EFL 1.23. /// /// The buffer to be appended. /// true on success, false if data could not be appended. public bool Append(Binbuf bb) { Contract.Requires(bb != null, nameof(bb)); return 0 != eina_binbuf_append_buffer(Handle, bb.Handle); } /// /// Appends a character to the buffer, reallocating as necessary. /// Since EFL 1.23. /// /// The char to appended. /// true on success, false if data could not be appended. public bool Append(byte c) { return 0 != eina_binbuf_append_char(Handle, c); } /// /// Appends a slice to the buffer, reallocating as necessary. /// Since EFL 1.23. /// /// The slice to appended. /// true on success, false if data could not be appended. public bool Append(Eina.Slice slice) { return 0 != eina_binbuf_append_slice(Handle, slice); } /// /// Inserts a string of inputed buffer's length into the buffer, /// reallocating as necessary. /// Since EFL 1.23. /// /// The string buffer. /// The position to insert the string. /// true on success, false if data could not be appended. public bool Insert(byte[] str, uint pos) { Contract.Requires(str != null, nameof(str)); return 0 != eina_binbuf_insert_length(Handle, str, (UIntPtr)(str.Length), (UIntPtr)pos); } /// /// Inserts a string of exact length into the buffer, /// reallocating as necessary. /// Since EFL 1.23. /// /// The string buffer. /// The exact length to use. /// The position to insert the string. /// true on success, false if data could not be appended. public bool Insert(byte[] str, uint length, uint pos) { return 0 != eina_binbuf_insert_length(Handle, str, (UIntPtr)length, (UIntPtr)pos); } /// /// Inserts a character into the buffer, reallocating as necessary. /// Since EFL 1.23. /// /// The char to appended. /// The position to insert the string. /// true on success, false if data could not be appended. public bool Insert(byte c, uint pos) { return 0 != eina_binbuf_insert_char(Handle, c, (UIntPtr)pos); } /// /// Inserts a slice into the buffer, reallocating as necessary. /// Since EFL 1.23. /// /// The slice to appended. /// The position to insert the string. /// true on success, false if data could not be appended. public bool Insert(Eina.Slice slice, uint pos) { return 0 != eina_binbuf_insert_slice(Handle, slice, (UIntPtr)pos); } /// /// Removes a slice of the buffer. /// Since EFL 1.23. /// /// The initial (inclusive) slice position to start /// removing, in bytes. /// The final (non-inclusive) slice position to finish /// removing, in bytes.. /// true on success, false on failure. public bool Remove(uint start, uint end) { return 0 != eina_binbuf_remove(Handle, (UIntPtr)start, (UIntPtr)end); } /// /// Retrieves a string to the contents of the buffer. /// Since EFL 1.23. /// /// The string that is contained in buffer. public byte[] GetBytes() { var ptr = eina_binbuf_string_get(Handle); if (ptr == IntPtr.Zero) { return null; } var size = (int)(this.GetLength()); byte[] mArray = new byte[size]; Marshal.Copy(ptr, mArray, 0, size); return mArray; } /// /// Retrieves a string to the contents of the buffer. /// /// The string that is contained in buffer. [EditorBrowsable(EditorBrowsableState.Never)] public IntPtr GetStringNative() { return eina_binbuf_string_get(Handle); } /// /// Frees the buffer. /// Since EFL 1.23. /// public void FreeString() { eina_binbuf_string_free(Handle); } /// /// Retrieves the length of the buffer's contents. /// Since EFL 1.23. /// public UIntPtr GetLength() { return eina_binbuf_length_get(Handle); } /// /// Gets a slice of the buffer's contents. /// Since EFL 1.23. /// public Eina.Slice GetSlice() { return eina_binbuf_slice_get(Handle); } } }