/*
 * 作者:吴隆健
 * 日期: 2019-04-07
 * 时间: 20:05
 * 
 */

#if BINARY
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace MrWu.Binary {
    /// <summary>
    /// 二进制装换类
    /// </summary>
    public static class BinaryConvert {
        
        /// <summary>
        /// 结构体转 bytes
        /// </summary>
        /// <param name="structObj">结构体</param>
        /// <param name="bytes">接收体</param>
        /// <param name="index">从第几个位置开始接收</param>
        public static void StructToBytes(object structObj, byte[] bytes, int index = 0) {
            int size = Marshal.SizeOf(structObj.GetType());
            IntPtr p = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, p, false);
            //从内存空间拷贝到byte 数组
            Marshal.Copy(p, bytes, index, size);
            //释放内存空间
            Marshal.FreeHGlobal(p);
        }
        
        /// <summary>
        /// 结构体转bytes
        /// </summary>
        /// <param name="structObj"></param>
        /// <returns></returns>
        public static byte[] StructToBytes(object structObj){
        	int size = Marshal.SizeOf(structObj.GetType());
        	byte[] bts = new byte[size];
        	StructToBytes(structObj,bts);
        	return bts;
        }
        

        /// <summary>
        /// bytes转结构体
        /// </summary>
        /// <typeparam name="T">结构体类型</typeparam>
        /// <param name="bytes">数据</param>
        /// <param name="idx">从第几个位置开始转换</param>
        /// <returns>转成的结构体</returns>
        public static T BytesToStruct<T>(byte[] bytes, int idx = 0) where T : struct{
            Type type = typeof(T);
            int size = Marshal.SizeOf(type);
            //分配结构体内存空间
            IntPtr p = Marshal.AllocHGlobal(size);
            //将byte数组拷贝到分配好的内存空间
            Marshal.Copy(bytes, idx, p, size);

            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(p, type);
            //释放内存空间
            Marshal.FreeHGlobal(p);
            return (T)obj;
        }

        /// <summary>
        /// bytes转字符串
        /// </summary>
        /// <param name="bytes">字节数</param>
        /// <param name="count"></param>
        /// <param name="index"></param>
        /// <param name="charset">编码 默认utf8</param>
        /// <returns>字符串</returns>           
        public static string BytesToString(byte[] bytes,int index = 0,int count = 0,Encoding charset = null) {
            if (charset == null)
                charset = Encoding.UTF8;
            if (count <= 0)
                count = bytes.Length;

            return charset.GetString(bytes,index,count);
        }

        /// <summary>
        /// 字符串转bytes
        /// </summary>
        /// <param name="chars">字符串</param>
        /// <param name="charset">编码 默认utf8</param>
        /// <returns>结果</returns>
        public static byte[] StringToBytes(string chars,Encoding charset = null) {
            if (charset == null)
                charset = Encoding.UTF8;
            
            return charset.GetBytes(chars);
        }
        
        /// <summary>
        /// 字符串转bytes
        /// </summary>
        /// <param name="chars">字符串</param>
        /// <param name="bts">接收的字节</param>
        /// <param name="index">起始位置</param>
        /// <param name="charset">编码 默认utf8</param>
        /// <returns>返回byte的长度</returns>
        public static int StringToBytes(string chars,byte[] bts,int index,Encoding charset = null){
        	if(charset == null)
        		charset = Encoding.UTF8;
        	
        	byte[] tmp_bts = StringToBytes(chars,charset);
        	Buffer.BlockCopy(tmp_bts,0,bts,index,tmp_bts.Length);
        	return tmp_bts.Length;
        }
        
        /// <summary>
        /// bytes 短字符串 第一个字节表示字符串长度
        /// </summary>
        /// <param name="bts">byte数组</param>
        /// <param name="charset">编码</param>
        /// <returns>字符串</returns>
        public static string BytesToShortString(byte[] bts,Encoding charset = null){
        	if(bts[0] == 0)
        		return string.Empty;
        	
        	return BytesToString(bts,1,bts[0],charset);
        }
        
        /// <summary>
        /// 短字符串bytes
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="charset">编码</param>
        /// <returns></returns>
        public static byte[] ShortStringToBytes(string str,Encoding charset = null){
        	if(charset == null)
        		charset = Encoding.UTF8;
        	
        	byte[] bts = StringToBytes(str,charset);
        	int len = bts.Length;
        	byte[] result = new byte[len+1];
        	result[0] = checked((byte)len);
        	Buffer.BlockCopy(bts,0,result,1,len);
        	return result;
        }
        
        /// <summary>
        /// 短字符串转bytes
        /// </summary>
        /// <param name="str"></param>
        /// <param name="bts"></param>
        /// <param name="index"></param>
        /// <param name="charset"></param>
        /// <returns></returns>
        public static int ShortStringToBytes(string str,byte[] bts,int index = 0,Encoding charset = null){
        	if(charset == null)
        		charset = Encoding.UTF8;
        	
        	byte[] rs = StringToBytes(str,charset);
        	int len = rs.Length;
        	bts[index]=checked((byte)len);
        	Buffer.BlockCopy(rs,0,bts,index+1,len);
        	return len + 1;
        }
        
        /// <summary>
        /// Dephi存储使用的编码
        /// </summary>
        public static Encoding GB2312{
        	get{
        		return Encoding.GetEncoding("GB2312");
        	}
        }
    }
}
#endif