/// <summary> /// 버퍼에 T형식의 변수의 값을 채워넣음. /// </summary> /// <typeparam name="T">형식</typeparam> /// <param name="src">버퍼에 넣을 값을 가진 변수</param> /// <param name="buffer">버퍼</param> /// <param name="buffIndex">버퍼의 byte위치</param> public static void FillBufferUnitsFrom <T>(T src, Array buffer, int startIndex, bool isSwap = false) { T[] val = new T[1]; val[0] = src; int valueTypeSize = Marshal.SizeOf(val[0]); int buffTypeSize = Marshal.SizeOf(buffer.GetValue(0)); if (isSwap) { Swaper.swapWithSize(val, buffer, valueTypeSize, valueTypeSize, 0, startIndex); } else { if (valueTypeSize < buffTypeSize) { Buffer.BlockCopy(val, 0, buffer, startIndex, valueTypeSize); } else { Buffer.BlockCopy(val, 0, buffer, startIndex, buffTypeSize); /* * int numOfIndex = buffTypeSize / valueTypeSize; * for (int i = 0; i < numOfIndex; i++) * { * * Buffer.BlockCopy(val, i * buffTypeSize, buffer, startIndex + i * buffTypeSize, buffTypeSize); * } */ } } }
/// <summary> /// buffer에서 일정 크기만큼 가져와서 object 형식으로 가져온다. /// </summary> /// <typeparam name="T">리턴할 변수타입</typeparam> /// <param name="buffer">읽어올 버퍼</param> /// <param name="startByteOffset">버퍼상에서 byte offset</param> /// <param name="isSwap">Swap할것인지</param> /// <param name="swapBaseSize">Swap하는 기준크기. -1이면 T의 크기</param> /// <param name="size">버퍼에서 읽어올 크기. 이 크기만큼 읽어와서 Swap하여 T에 넣는다. -1이면 T의크기.</param> /// <returns></returns> public static object GetVariableSwapFromBuffer(Array buffer, Type type, int startByteOffset, Boolean isSwap = false, int swapBaseSize = -1, int size = -1) { //swapBaseSize = (swapBaseSize < 0) ? Marshal.SizeOf(buffer.GetValue(0)) : swapBaseSize; swapBaseSize = (swapBaseSize < 0) ? Marshal.SizeOf(type) : swapBaseSize; Array val = GetBufferFromType(type, 1); int valueTypeSize = Marshal.SizeOf(type); if (size > 0) { if (valueTypeSize < size) { throw new Exception("size of T type must be bigger than 'size'. 'size' is the size to read from buffer"); } else { valueTypeSize = size; } } if (swapBaseSize < valueTypeSize) { throw new Exception("swapBaseSize must be bigger than size"); } if (isSwap == false) {//little Endian기준으로는 앞에서 잘라오면 된다. Buffer.BlockCopy(buffer, startByteOffset, val, 0, valueTypeSize); } else { Swaper.swapWithSize(buffer, val, swapBaseSize, size, startByteOffset, 0); } return(val.GetValue(0)); }
public static T[] ConvertToArray <T>(string p, Type type, bool swap = true) where T : IConvertible, IComparable, IFormattable { TypeCode tCode = Type.GetTypeCode(type); int baseTSize = Marshal.SizeOf(type); int arrTSize = Marshal.SizeOf(typeof(T)); T[] arr; if (arrTSize >= baseTSize) { arr = new T[1]; } else { arr = new T[baseTSize / arrTSize]; } try { Array temp; switch (tCode) { case TypeCode.Byte: temp = new byte[] { byte.Parse(p) }; break; case TypeCode.Int16: temp = new Int16[] { Int16.Parse(p) }; break; case TypeCode.Int32: temp = new Int32[] { Int32.Parse(p) }; break; case TypeCode.Int64: temp = new Int64[] { Int64.Parse(p) }; break; case TypeCode.SByte: temp = new SByte[] { SByte.Parse(p) }; break; case TypeCode.UInt16: temp = new UInt16[] { UInt16.Parse(p) }; break; case TypeCode.UInt32: temp = new UInt32[] { UInt32.Parse(p) }; break; case TypeCode.UInt64: temp = new UInt64[] { UInt64.Parse(p) }; break; case TypeCode.Double: temp = new Double[] { Double.Parse(p) }; break; case TypeCode.Single: temp = new Single[] { Single.Parse(p) }; break; default: throw new Exception("DataHandling.TypeArrayConverter.ConvertToArray() - only number can be handled..."); } if (swap) { Swaper.swapWithSize(temp, arr, arrTSize, arrTSize, 0, 0); return(arr); } else { Buffer.BlockCopy(temp, 0, arr, 0, arrTSize); return(arr); } } catch (Exception ex) { throw new Exception("DataHandling.TypeArrayConverter.ConvertToArray() - \r\nvalue: " + p + "/ type:" + type.ToString() + "\r\n" + ex.Message); } }
/// <summary> /// 버퍼에 있는 내용을 그냥 value에 집어넣으면 버퍼의 할당크기와 변수의 바이트크기가 다를 경우 /// signed와 unsigned를 잡을 수 없다. /// 따라서 부호를 인식해 주는 작업과 부호에 따라서 복사를 달리해야 한다. /// 이 메서드는 버퍼에 있는 내용을 U타입이 signed인지 판단한 이후에 알맞은 /// converting을 통해서 U타입에 넣어준다. float과 double도 이와 같은 과정을 통해 /// 부호와 타입이 정해진다. /// </summary> /// <typeparam name="U"></typeparam> /// <param name="buffer"></param> /// <param name="startByteOffset"></param> /// <param name="byteSizes"></param> /// <param name="isUnsigned"></param> /// <returns></returns> public static U CopyBufferToVariable <U>(Array buffer, int startByteOffset, int byteSizes = -1, Boolean isUnsigned = false, Boolean isSwap = false) { int typeSize = Marshal.SizeOf(typeof(U)); byteSizes = (byteSizes < 0) ? typeSize: byteSizes; U[] value = new U[1]; if ((value[0] is SByte) || (value[0] is Int16) || (value[0] is Int32) || (value[0] is Int64)) { //signed value if (isMinus(buffer, startByteOffset, byteSizes)) { CopyIntToArray(-1, value, typeSize); } else { CopyIntToArray(0, value, typeSize); //부호를 맞추고 } if (isSwap) { Swaper.swapWithSize(buffer, value, byteSizes, byteSizes, startByteOffset, 0); } else { Buffer.BlockCopy(buffer, startByteOffset, value, 0, byteSizes); } } else if ((value[0] is Byte) || (value[0] is UInt16) || (value[0] is UInt32) || (value[0] is UInt64)) {//unsigned values CopyIntToArray(0, value, typeSize); if (isSwap) { Swaper.swapWithSize(buffer, value, byteSizes, byteSizes, startByteOffset, 0); } else { Buffer.BlockCopy(buffer, startByteOffset, value, 0, byteSizes); } } else if ((value[0] is Single) || (value[0] is Double)) {//floating point Single[] sing = new Single[1]; Double[] doub = new Double[1]; if (byteSizes == 4) { if (typeSize == 8) { Buffer.BlockCopy(buffer, startByteOffset, sing, 0, byteSizes); doub[0] = (Double)sing[0]; //버퍼의 내용은 single이고 가져갈 내용은 double이므로 일단 single형식에 //buffer copy를 하고, 캐스팅을 통해 값을 넣어준다. if (isSwap) { Swaper.swapWithSize(doub, value, byteSizes, byteSizes, 0, 0); } else { Buffer.BlockCopy(doub, 0, value, 0, typeSize); } } else //4 - single: 가져갈 값과 버퍼의 내용 동일하므로 바로 복사해줌. { if (isSwap) { Swaper.swapWithSize(buffer, value, typeSize, typeSize, startByteOffset, 0); } else { Buffer.BlockCopy(buffer, startByteOffset, value, 0, typeSize); } // Buffer.BlockCopy(buffer, startByteOffset, value, 0, typeSize); } } else //8 { if (typeSize == 4) { Buffer.BlockCopy(buffer, startByteOffset, doub, 0, byteSizes); sing[0] = (Single)doub[0]; //버퍼의 내용은 double이고 가져갈 내용은 single이므로 일단 double형식에 //buffer copy를 하고, 캐스팅을 통해 값을 넣어준다. //Buffer.BlockCopy(sing, 0, value, 0, typeSize); if (isSwap) { Swaper.swapWithSize(doub, value, typeSize, typeSize, 0, 0); } else { Buffer.BlockCopy(sing, 0, value, 0, typeSize); } } else //8 - double: 가져갈 값과 버퍼의 내용 동일하므로 바로 복사해줌. { if (isSwap) { Swaper.swapWithSize(buffer, value, typeSize, typeSize, startByteOffset, 0); } else { Buffer.BlockCopy(buffer, startByteOffset, value, 0, typeSize); } //Buffer.BlockCopy(buffer, startByteOffset, value, 0, typeSize); } } } else//boolean { Int64[] a = new Int64[1]; CopyIntToArray(0, a); Buffer.BlockCopy(buffer, startByteOffset, a, 0, byteSizes); if (a[0] != 0) { CopyIntToArray(1, value); } else { CopyIntToArray(0, value); } } return(value[0]); }