/// <summary>
 /// Returns a delegate to read the specific column into a boxed 
 /// strongly typed variable
 /// </summary>
 /// <param name="column"></param>
 /// <returns></returns>
 private ByteReaderDelegate GetByteReaderDelegate(FitsTableColumn column)
 {
     // Complex types firts, then scalar and arrays
     if (column.DataType.Type == typeof(String))
     {
         return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
         {
             value = Encoding.ASCII.GetString(bytes, startIndex, count);
             return count;
         };
     }
     else if (column.DataType.Repeat == 1)
     {
         // Scalars
         if (column.DataType.Type == typeof(Boolean))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Boolean val;
                 var res = converter.ToBoolean(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(SByte))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 SByte val;
                 var res = converter.ToSByte(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Byte))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Byte val;
                 var res = converter.ToByte(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Char))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Char val;
                 var res = converter.ToChar(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int16))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int16 val;
                 var res = converter.ToInt16(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt16))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt16 val;
                 var res = converter.ToUInt16(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int32))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int32 val;
                 var res = converter.ToInt32(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt32))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt32 val;
                 var res = converter.ToUInt32(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int64))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int64 val;
                 var res = converter.ToInt64(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt64))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt64 val;
                 var res = converter.ToUInt64(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Single))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Single val;
                 var res = converter.ToSingle(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Double))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Double val;
                 var res = converter.ToDouble(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(SingleComplex))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 SingleComplex val;
                 var res = converter.ToSingleComplex(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(DoubleComplex))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 DoubleComplex val;
                 var res = converter.ToDoubleComplex(bytes, startIndex, out val);
                 value = val;
                 return res;
             };
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         // Arrays
         if (column.DataType.Type == typeof(Boolean))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Boolean[] val;
                 var res = converter.ToBoolean(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(SByte))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 SByte[] val;
                 var res = converter.ToSByte(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Byte))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Byte[] val;
                 var res = converter.ToByte(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Char))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Char[] val;
                 var res = converter.ToChar(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int16))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int16[] val;
                 var res = converter.ToInt16(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt16))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt16[] val;
                 var res = converter.ToUInt16(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int32))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int32[] val;
                 var res = converter.ToInt32(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt32))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt32[] val;
                 var res = converter.ToUInt32(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Int64))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Int64[] val;
                 var res = converter.ToInt64(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(UInt64))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 UInt64[] val;
                 var res = converter.ToUInt64(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Single))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Single[] val;
                 var res = converter.ToSingle(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(Double))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 Double[] val;
                 var res = converter.ToDouble(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(SingleComplex))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 SingleComplex[] val;
                 var res = converter.ToSingleComplex(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else if (column.DataType.Type == typeof(DoubleComplex))
         {
             return delegate(BitConverterBase converter, byte[] bytes, int startIndex, int count, out object value)
             {
                 DoubleComplex[] val;
                 var res = converter.ToDoubleComplex(bytes, startIndex, count, out val);
                 value = val;
                 return res;
             };
         }
         else
         {
             throw new NotImplementedException();
         }
     }
 }
 private void CopyMembers(FitsTableColumn old)
 {
     this.id = old.id;
     this.name = old.name;
     this.dataType = new FitsDataType(old.dataType);
     this.nullValue = old.nullValue;
     this.unit = old.unit;
     this.scale = old.scale;
     this.zero = old.zero;
     this.format = old.format;
     this.dimensions = old.dimensions;
 }
 public FitsTableColumn(FitsTableColumn old)
 {
     CopyMembers(old);
 }
        internal static FitsTableColumn CreateFromHeader(HduBase hdu, int index)
        {
            Card card;

            // Get data type
            if (!hdu.Cards.TryGetValue(Constants.FitsKeywordTForm, index, out card))
            {
                throw new FitsException("Keyword expected but not found:"); // TODO
            }

            var tform = card.GetString();
            var dt = FitsDataType.CreateFromTForm(tform);

            // Create column

            var column = new FitsTableColumn()
            {
                ID = index,
            };

            // Set optional parameters

            // --- Column name
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTType, index, out card))
            {
                column.Name = card.GetString();
            }

            // Unit
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTUnit, index, out card))
            {
                column.Unit = card.GetString();
            }

            // Null value equivalent
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTNull, index, out card))
            {
                column.NullValue = card.GetInt32();
            }

            // Scale
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTScal, index, out card))
            {
                column.Scale = card.GetDouble();
            }

            // Zero offset
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTZero, index, out card))
            {
                column.Zero = card.GetDouble();
            }

            // Format
            if (hdu.Cards.TryGetValue(Constants.FitsKeywordTDisp, index, out card))
            {
                column.Format = card.GetString();
            }

            return column;
        }