/***************************************************************************
 * Copyright (c) 2009 Digi International Inc., All Rights Reserved
 * 
 * This software contains proprietary and confidential information of Digi
 * International Inc.  By accepting transfer of this copy, Recipient agrees
 * to retain this software in confidence, to prevent disclosure to others,
 * and to make no use of this software other than that for which it was
 * delivered.  This is an unpublished copyrighted work of Digi International
 * Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 * prohibited.
 * 
 * Restricted Rights Legend
 *
 * Use, duplication, or disclosure by the Government is subject to
 * restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 * Technical Data and Computer Software clause at DFARS 252.227-7031 or
 * subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 * Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 ***************************************************************************
 *
 * @Descr: CStructBuilder
 *
 * @History:
 *
 ***************************************************************************/

using System;
using System.Text;
using System.Runtime.InteropServices; // dll support

namespace Digi.Common
{
    public class StructBuilder
    {
        private static class dll
        {
            [DllImport("CStructBuilder.dll")]
            public static extern IntPtr Create(int size);

            [DllImport("CStructBuilder.dll")]
            public static extern void Delete(IntPtr handle);

            [DllImport("CStructBuilder.dll")]
            public static extern void Set(IntPtr handle, int start, byte[] data, int length);

            [DllImport("CStructBuilder.dll")]
            public static extern void Set_Pointer(IntPtr handle, int start, IntPtr data);

            [DllImport("CStructBuilder.dll")]
            public static extern void Get(IntPtr handle, int start, int length, byte[] data);

            [DllImport("CStructBuilder.dll")]
            public static extern IntPtr Get_Pointer(IntPtr handle, int start);
        }

        private IntPtr Handle;
        private int Size;

        public StructBuilder(int size)
        {
            Size = size;
            Handle = dll.Create(size);
        }

        ~StructBuilder()
        {
            dll.Delete(Handle);
        }

        public void Destroy()
        {
            dll.Delete(Handle);
        }

        public void Set(int start, byte[] data)
        {
            Set(start, data, Math.Min(data.Length, Size));
        }

        public void Set(int start, byte[] data, int length)
        {
            if (length > Size)
                throw new Exception("StructBuilder.Set(int,byte[],int): Data length is greater than allocated size.");

            dll.Set(Handle, start, data, length);
        }

        public void SetStruct(int start, StructBuilder data)
        {
            SetStruct(start, data.GetHandle());
        }

        private void SetStruct(int start, IntPtr data)
        {
            dll.Set_Pointer(Handle, start, data);
        }

        public int GetSize()
        {
            return Size;
        }

        public IntPtr GetHandle()
        {
            return Handle;
        }

        public void Get(int start, ref byte[] buff)
        {
            Get(start, Math.Min(buff.Length, Size), ref buff);
        }

        public void Get(int start, int length, ref byte[] buff)
        {
            if (start + length > Size)
                throw new Exception("StructBuilder.Get(int,int,ref byte[]): Start + Length > Size");

            dll.Get(Handle, start, length, buff);
        }

/*      Too risky. This is disabled.
        public StructBuilder GetStruct(int start)
        {
            StructBuilder s = new StructBuilder(1);
            dll.Delete(data.Handle);
            GetStruct(start, ref data.Handle);
        }

        private IntPtr GetStruct(int start)
        {
            return dll.Get_Pointer(Handle, start);
        }*/

    }
}
