github.com/sbinet/go-cfitsio@v0.0.0-20140625105338-0307f985659e/column.go (about)

     1  package cfitsio
     2  
     3  // #include <complex.h>
     4  // #include "go-cfitsio.h"
     5  // #include "go-cfitsio-utils.h"
     6  import "C"
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  // Value is a value in a FITS table
    14  type Value interface{}
    15  
    16  // Column represents a column in a FITS table
    17  type Column struct {
    18  	Name    string  // column name, corresponding to ``TTYPE`` keyword
    19  	Format  string  // column format, corresponding to ``TFORM`` keyword
    20  	Unit    string  // column unit, corresponding to ``TUNIT`` keyword
    21  	Null    string  // null value, corresponding to ``TNULL`` keyword
    22  	Bscale  float64 // bscale value, corresponding to ``TSCAL`` keyword
    23  	Bzero   float64 // bzero value, corresponding to ``TZERO`` keyword
    24  	Display string  // display format, corresponding to ``TDISP`` keyword
    25  	Dim     []int64 // column dimension corresponding to ``TDIM`` keyword
    26  	Start   int64   // column starting position, corresponding to ``TBCOL`` keyword
    27  	IsVLA   bool    // whether this is a variable length array
    28  	Value   Value   // value at current row
    29  }
    30  
    31  // inferFormat infers the FITS format associated with a Column, according to its HDUType and Go type.
    32  func (col *Column) inferFormat(htype HDUType) error {
    33  	var err error
    34  	if col.Format != "" {
    35  		return nil
    36  	}
    37  
    38  	str := gotype2FITS(col.Value, htype)
    39  	if str == "" {
    40  		return fmt.Errorf("cfitsio: %v can not handle [%T]", htype, col.Value)
    41  	}
    42  	col.Format = str
    43  	return err
    44  }
    45  
    46  // read reads the value at column number icol and row irow, into ptr.
    47  // icol and irow are 0-based indices.
    48  func (col *Column) read(f *File, icol int, irow int64, ptr interface{}) error {
    49  	var err error
    50  
    51  	c_type := C.int(0)
    52  	c_icol := C.int(icol + 1)      // 0-based to 1-based index
    53  	c_irow := C.LONGLONG(irow + 1) // 0-based to 1-based index
    54  	c_anynul := C.int(0)
    55  	c_status := C.int(0)
    56  
    57  	var value interface{}
    58  	rv := reflect.ValueOf(ptr).Elem()
    59  	rt := reflect.TypeOf(rv.Interface())
    60  
    61  	switch rt.Kind() {
    62  	case reflect.Bool:
    63  		c_type = C.TLOGICAL
    64  		c_value := C.char(0) // 'F'
    65  		c_ptr := unsafe.Pointer(&c_value)
    66  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
    67  		value = c_value == 1
    68  
    69  	case reflect.Uint8:
    70  		c_type = C.TBYTE
    71  		var c_value C.char
    72  		c_ptr := unsafe.Pointer(&c_value)
    73  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
    74  		value = byte(c_value)
    75  
    76  	case reflect.Uint16:
    77  		c_type = C.TUSHORT
    78  		var c_value C.ushort
    79  		c_ptr := unsafe.Pointer(&c_value)
    80  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
    81  		value = uint16(c_value)
    82  
    83  	case reflect.Uint32:
    84  		c_type = C.TUINT
    85  		var c_value C.uint
    86  		c_ptr := unsafe.Pointer(&c_value)
    87  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
    88  		value = uint32(c_value)
    89  
    90  	case reflect.Uint64:
    91  		c_type = C.TULONG
    92  		var c_value C.ulong
    93  		c_ptr := unsafe.Pointer(&c_value)
    94  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
    95  		value = uint64(c_value)
    96  
    97  	case reflect.Uint:
    98  		c_type = C.TULONG
    99  		var c_value C.ulong
   100  		c_ptr := unsafe.Pointer(&c_value)
   101  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   102  		value = uint(c_value)
   103  
   104  	case reflect.Int8:
   105  		c_type = C.TSBYTE
   106  		var c_value C.char
   107  		c_ptr := unsafe.Pointer(&c_value)
   108  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   109  		value = int8(c_value)
   110  
   111  	case reflect.Int16:
   112  		c_type = C.TSHORT
   113  		var c_value C.short
   114  		c_ptr := unsafe.Pointer(&c_value)
   115  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   116  		value = int16(c_value)
   117  
   118  	case reflect.Int32:
   119  		c_type = C.TINT
   120  		var c_value C.int
   121  		c_ptr := unsafe.Pointer(&c_value)
   122  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   123  		value = int32(c_value)
   124  
   125  	case reflect.Int64:
   126  		c_type = C.TLONG
   127  		var c_value C.long
   128  		c_ptr := unsafe.Pointer(&c_value)
   129  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   130  		value = int64(c_value)
   131  
   132  	case reflect.Int:
   133  		c_type = C.TLONG
   134  		var c_value C.long
   135  		c_ptr := unsafe.Pointer(&c_value)
   136  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   137  		value = int(c_value)
   138  
   139  	case reflect.Float32:
   140  		c_type = C.TFLOAT
   141  		var c_value C.float
   142  		c_ptr := unsafe.Pointer(&c_value)
   143  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   144  		value = float32(c_value)
   145  
   146  	case reflect.Float64:
   147  		c_type = C.TDOUBLE
   148  		var c_value C.double
   149  		c_ptr := unsafe.Pointer(&c_value)
   150  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   151  		value = float64(c_value)
   152  
   153  	case reflect.Complex64:
   154  		c_type = C.TCOMPLEX
   155  		var c_value C.complexfloat
   156  		c_ptr := unsafe.Pointer(&c_value)
   157  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   158  		value = complex(
   159  			float32(C.crealf(c_value)),
   160  			float32(C.cimagf(c_value)),
   161  		)
   162  
   163  	case reflect.Complex128:
   164  		c_type = C.TDBLCOMPLEX
   165  		var c_value C.complexdouble
   166  		c_ptr := unsafe.Pointer(&c_value)
   167  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   168  		value = complex(
   169  			float64(C.creal(c_value)),
   170  			float64(C.cimag(c_value)),
   171  		)
   172  
   173  	case reflect.String:
   174  		c_type = C.TSTRING
   175  		// FIXME: get correct maximum size from card
   176  		c_value := C.CStringN(C.FLEN_FILENAME)
   177  		defer C.free(unsafe.Pointer(c_value))
   178  		c_ptr := unsafe.Pointer(&c_value)
   179  		C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   180  		value = C.GoString(c_value)
   181  
   182  	case reflect.Array:
   183  		c_len := C.LONGLONG(rt.Len())
   184  		switch rt.Elem().Kind() {
   185  		case reflect.Bool:
   186  			c_type = C.TLOGICAL
   187  			v := make([]bool, int(c_len), int(c_len))
   188  			value = v
   189  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   190  			c_ptr := unsafe.Pointer(slice.Data)
   191  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   192  
   193  		case reflect.Uint8:
   194  			c_type = C.TBYTE
   195  			v := make([]uint8, int(c_len), int(c_len))
   196  			value = v
   197  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   198  			c_ptr := unsafe.Pointer(slice.Data)
   199  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   200  
   201  		case reflect.Uint16:
   202  			c_type = C.TUSHORT
   203  			v := make([]uint16, int(c_len), int(c_len))
   204  			value = v
   205  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   206  			c_ptr := unsafe.Pointer(slice.Data)
   207  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   208  
   209  		case reflect.Uint32:
   210  			c_type = C.TUINT
   211  			v := make([]uint32, int(c_len), int(c_len))
   212  			value = v
   213  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   214  			c_ptr := unsafe.Pointer(slice.Data)
   215  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   216  
   217  		case reflect.Uint64:
   218  			c_type = C.TULONG
   219  			v := make([]uint64, int(c_len), int(c_len))
   220  			value = v
   221  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   222  			c_ptr := unsafe.Pointer(slice.Data)
   223  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   224  
   225  		case reflect.Uint:
   226  			c_type = C.TULONG
   227  			v := make([]uint, int(c_len), int(c_len))
   228  			value = v
   229  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   230  			c_ptr := unsafe.Pointer(slice.Data)
   231  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   232  
   233  		case reflect.Int8:
   234  			c_type = C.TSBYTE
   235  			v := make([]int8, int(c_len), int(c_len))
   236  			value = v
   237  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   238  			c_ptr := unsafe.Pointer(slice.Data)
   239  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   240  
   241  		case reflect.Int16:
   242  			c_type = C.TSHORT
   243  			v := make([]int16, int(c_len), int(c_len))
   244  			value = v
   245  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   246  			c_ptr := unsafe.Pointer(slice.Data)
   247  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   248  
   249  		case reflect.Int32:
   250  			c_type = C.TINT
   251  			v := make([]int32, int(c_len), int(c_len))
   252  			value = v
   253  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   254  			c_ptr := unsafe.Pointer(slice.Data)
   255  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   256  
   257  		case reflect.Int64:
   258  			c_type = C.TLONG
   259  			v := make([]int64, int(c_len), int(c_len))
   260  			value = v
   261  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   262  			c_ptr := unsafe.Pointer(slice.Data)
   263  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   264  
   265  		case reflect.Int:
   266  			c_type = C.TLONG
   267  			v := make([]int, int(c_len), int(c_len))
   268  			value = v
   269  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   270  			c_ptr := unsafe.Pointer(slice.Data)
   271  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   272  
   273  		case reflect.Float32:
   274  			c_type = C.TFLOAT
   275  			v := make([]float32, int(c_len), int(c_len))
   276  			value = v
   277  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   278  			c_ptr := unsafe.Pointer(slice.Data)
   279  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   280  
   281  		case reflect.Float64:
   282  			c_type = C.TDOUBLE
   283  			v := make([]float64, int(c_len), int(c_len))
   284  			value = v
   285  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   286  			c_ptr := unsafe.Pointer(slice.Data)
   287  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   288  
   289  		case reflect.Complex64:
   290  			c_type = C.TCOMPLEX
   291  			v := make([]complex64, int(c_len), int(c_len)) // FIXME: assume same binary layout
   292  			value = v
   293  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   294  			c_ptr := unsafe.Pointer(slice.Data)
   295  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   296  
   297  		case reflect.Complex128:
   298  			c_type = C.TDBLCOMPLEX
   299  			v := make([]complex128, int(c_len), int(c_len)) // FIXME: assume same binary layout
   300  			value = v
   301  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   302  			c_ptr := unsafe.Pointer(slice.Data)
   303  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   304  		default:
   305  			panic(fmt.Errorf("invalid type [%T]", value))
   306  		}
   307  
   308  	case reflect.Slice:
   309  		switch rt.Elem().Kind() {
   310  		case reflect.Bool:
   311  			c_type = C.TLOGICAL
   312  			c_len := C.long(0)
   313  			c_off := C.long(0)
   314  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   315  			if c_status > 0 {
   316  				err = to_err(c_status)
   317  				return err
   318  			}
   319  			v := make([]bool, int(c_len), int(c_len))
   320  			value = v
   321  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   322  			c_ptr := unsafe.Pointer(slice.Data)
   323  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   324  
   325  		case reflect.Uint8:
   326  			c_type = C.TBYTE
   327  			c_len := C.long(0)
   328  			c_off := C.long(0)
   329  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   330  			if c_status > 0 {
   331  				err = to_err(c_status)
   332  				return err
   333  			}
   334  			v := make([]uint8, int(c_len), int(c_len))
   335  			value = v
   336  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   337  			c_ptr := unsafe.Pointer(slice.Data)
   338  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   339  
   340  		case reflect.Uint16:
   341  			c_type = C.TUSHORT
   342  			c_len := C.long(0)
   343  			c_off := C.long(0)
   344  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   345  			if c_status > 0 {
   346  				err = to_err(c_status)
   347  				return err
   348  			}
   349  			v := make([]uint16, int(c_len), int(c_len))
   350  			value = v
   351  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   352  			c_ptr := unsafe.Pointer(slice.Data)
   353  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   354  
   355  		case reflect.Uint32:
   356  			c_type = C.TUINT
   357  			c_len := C.long(0)
   358  			c_off := C.long(0)
   359  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   360  			if c_status > 0 {
   361  				err = to_err(c_status)
   362  				return err
   363  			}
   364  			v := make([]uint32, int(c_len), int(c_len))
   365  			value = v
   366  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   367  			c_ptr := unsafe.Pointer(slice.Data)
   368  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   369  
   370  		case reflect.Uint64:
   371  			c_type = C.TULONG
   372  			c_len := C.long(0)
   373  			c_off := C.long(0)
   374  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   375  			if c_status > 0 {
   376  				err = to_err(c_status)
   377  				return err
   378  			}
   379  			v := make([]uint64, int(c_len), int(c_len))
   380  			value = v
   381  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   382  			c_ptr := unsafe.Pointer(slice.Data)
   383  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   384  
   385  		case reflect.Uint:
   386  			c_type = C.TULONG
   387  			c_len := C.long(0)
   388  			c_off := C.long(0)
   389  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   390  			if c_status > 0 {
   391  				err = to_err(c_status)
   392  				return err
   393  			}
   394  			v := make([]uint, int(c_len), int(c_len))
   395  			value = v
   396  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   397  			c_ptr := unsafe.Pointer(slice.Data)
   398  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   399  
   400  		case reflect.Int8:
   401  			c_type = C.TSBYTE
   402  			c_len := C.long(0)
   403  			c_off := C.long(0)
   404  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   405  			if c_status > 0 {
   406  				err = to_err(c_status)
   407  				return err
   408  			}
   409  			v := make([]int8, int(c_len), int(c_len))
   410  			value = v
   411  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   412  			c_ptr := unsafe.Pointer(slice.Data)
   413  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   414  
   415  		case reflect.Int16:
   416  			c_type = C.TSHORT
   417  			c_len := C.long(0)
   418  			c_off := C.long(0)
   419  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   420  			if c_status > 0 {
   421  				err = to_err(c_status)
   422  				return err
   423  			}
   424  			v := make([]int16, int(c_len), int(c_len))
   425  			value = v
   426  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   427  			c_ptr := unsafe.Pointer(slice.Data)
   428  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   429  
   430  		case reflect.Int32:
   431  			c_type = C.TINT
   432  			c_len := C.long(0)
   433  			c_off := C.long(0)
   434  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   435  			if c_status > 0 {
   436  				err = to_err(c_status)
   437  				return err
   438  			}
   439  			v := make([]int32, int(c_len), int(c_len))
   440  			value = v
   441  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   442  			c_ptr := unsafe.Pointer(slice.Data)
   443  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   444  
   445  		case reflect.Int64:
   446  			c_type = C.TLONG
   447  			c_len := C.long(0)
   448  			c_off := C.long(0)
   449  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   450  			if c_status > 0 {
   451  				err = to_err(c_status)
   452  				return err
   453  			}
   454  			v := make([]int64, int(c_len), int(c_len))
   455  			value = v
   456  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   457  			c_ptr := unsafe.Pointer(slice.Data)
   458  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   459  
   460  		case reflect.Int:
   461  			c_type = C.TLONG
   462  			c_len := C.long(0)
   463  			c_off := C.long(0)
   464  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   465  			if c_status > 0 {
   466  				err = to_err(c_status)
   467  				return err
   468  			}
   469  			v := make([]int, int(c_len), int(c_len))
   470  			value = v
   471  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   472  			c_ptr := unsafe.Pointer(slice.Data)
   473  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   474  
   475  		case reflect.Float32:
   476  			c_type = C.TFLOAT
   477  			c_len := C.long(0)
   478  			c_off := C.long(0)
   479  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   480  			if c_status > 0 {
   481  				err = to_err(c_status)
   482  				return err
   483  			}
   484  			v := make([]float32, int(c_len), int(c_len))
   485  			value = v
   486  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   487  			c_ptr := unsafe.Pointer(slice.Data)
   488  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   489  
   490  		case reflect.Float64:
   491  			c_type = C.TDOUBLE
   492  			c_len := C.long(0)
   493  			c_off := C.long(0)
   494  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   495  			if c_status > 0 {
   496  				err = to_err(c_status)
   497  				return err
   498  			}
   499  			v := make([]float64, int(c_len), int(c_len))
   500  			value = v
   501  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   502  			c_ptr := unsafe.Pointer(slice.Data)
   503  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   504  
   505  		case reflect.Complex64:
   506  			c_type = C.TCOMPLEX
   507  			c_len := C.long(0)
   508  			c_off := C.long(0)
   509  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   510  			if c_status > 0 {
   511  				err = to_err(c_status)
   512  				return err
   513  			}
   514  			v := make([]complex64, int(c_len), int(c_len)) // FIXME: assume same binary layout
   515  			value = v
   516  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   517  			c_ptr := unsafe.Pointer(slice.Data)
   518  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   519  
   520  		case reflect.Complex128:
   521  			c_type = C.TDBLCOMPLEX
   522  			c_len := C.long(0)
   523  			c_off := C.long(0)
   524  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   525  			if c_status > 0 {
   526  				err = to_err(c_status)
   527  				return err
   528  			}
   529  			v := make([]complex128, int(c_len), int(c_len)) // FIXME: assume same binary layout
   530  			value = v
   531  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   532  			c_ptr := unsafe.Pointer(slice.Data)
   533  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(c_len), nil, c_ptr, &c_anynul, &c_status)
   534  		default:
   535  			panic(fmt.Errorf("invalid type [%T]", value))
   536  		}
   537  
   538  	default:
   539  		panic(fmt.Errorf("invalid type [%T]", value))
   540  	}
   541  
   542  	if c_status > 0 {
   543  		err = to_err(c_status)
   544  	}
   545  
   546  	rv.Set(reflect.ValueOf(value))
   547  	col.Value = value
   548  	return err
   549  }
   550  
   551  // write writes the current value of this Column into file f at column icol and row irow.
   552  // icol and irow are 0-based indices.
   553  func (col *Column) write(f *File, icol int, irow int64, value interface{}) error {
   554  	var err error
   555  
   556  	c_type := C.int(0)
   557  	c_icol := C.int(icol + 1)      // 0-based to 1-based index
   558  	c_irow := C.LONGLONG(irow + 1) // 0-based to 1-based index
   559  	c_status := C.int(0)
   560  
   561  	rv := reflect.ValueOf(value)
   562  	rt := reflect.TypeOf(value)
   563  
   564  	switch rt.Kind() {
   565  	case reflect.Bool:
   566  		c_type = C.TLOGICAL
   567  		c_value := C.char(0) // 'F'
   568  		if value.(bool) {
   569  			c_value = 1
   570  		}
   571  		c_ptr := unsafe.Pointer(&c_value)
   572  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   573  
   574  	case reflect.Uint8:
   575  		c_type = C.TBYTE
   576  		c_value := C.char(value.(byte))
   577  		c_ptr := unsafe.Pointer(&c_value)
   578  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   579  
   580  	case reflect.Uint16:
   581  		c_type = C.TUSHORT
   582  		c_value := C.ushort(value.(uint16))
   583  		c_ptr := unsafe.Pointer(&c_value)
   584  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   585  
   586  	case reflect.Uint32:
   587  		c_type = C.TUINT
   588  		c_value := C.uint(value.(uint32))
   589  		c_ptr := unsafe.Pointer(&c_value)
   590  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   591  
   592  	case reflect.Uint64:
   593  		c_type = C.TULONG
   594  		c_value := C.ulong(value.(uint64))
   595  		c_ptr := unsafe.Pointer(&c_value)
   596  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   597  
   598  	case reflect.Uint:
   599  		c_type = C.TULONG
   600  		c_value := C.ulong(value.(uint))
   601  		c_ptr := unsafe.Pointer(&c_value)
   602  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   603  
   604  	case reflect.Int8:
   605  		c_type = C.TSBYTE
   606  		c_value := C.char(value.(int8))
   607  		c_ptr := unsafe.Pointer(&c_value)
   608  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   609  
   610  	case reflect.Int16:
   611  		c_type = C.TSHORT
   612  		c_value := C.short(value.(int16))
   613  		c_ptr := unsafe.Pointer(&c_value)
   614  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   615  
   616  	case reflect.Int32:
   617  		c_type = C.TINT
   618  		c_value := C.int(value.(int32))
   619  		c_ptr := unsafe.Pointer(&c_value)
   620  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   621  
   622  	case reflect.Int64:
   623  		c_type = C.TLONG
   624  		c_value := C.long(value.(int64))
   625  		c_ptr := unsafe.Pointer(&c_value)
   626  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   627  
   628  	case reflect.Int:
   629  		c_type = C.TLONG
   630  		c_value := C.long(value.(int))
   631  		c_ptr := unsafe.Pointer(&c_value)
   632  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   633  
   634  	case reflect.Float32:
   635  		c_type = C.TFLOAT
   636  		c_value := C.float(value.(float32))
   637  		c_ptr := unsafe.Pointer(&c_value)
   638  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   639  
   640  	case reflect.Float64:
   641  		c_type = C.TDOUBLE
   642  		c_value := C.double(value.(float64))
   643  		c_ptr := unsafe.Pointer(&c_value)
   644  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   645  
   646  	case reflect.Complex64:
   647  		c_type = C.TCOMPLEX
   648  		value := value.(complex64)
   649  		c_ptr := unsafe.Pointer(&value) // FIXME: assumes same memory layout
   650  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   651  
   652  	case reflect.Complex128:
   653  		c_type = C.TDBLCOMPLEX
   654  		value := value.(complex128)
   655  		c_ptr := unsafe.Pointer(&value) // FIXME: assumes same memory layout
   656  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   657  
   658  	case reflect.String:
   659  		c_type = C.TSTRING
   660  		c_value := C.CString(value.(string))
   661  		defer C.free(unsafe.Pointer(c_value))
   662  		c_ptr := unsafe.Pointer(&c_value)
   663  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   664  
   665  	case reflect.Slice:
   666  		switch rt.Elem().Kind() {
   667  		case reflect.Bool:
   668  			c_type = C.TLOGICAL
   669  			value := value.([]bool)
   670  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   671  			c_ptr := unsafe.Pointer(slice.Data)
   672  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   673  
   674  		case reflect.Uint8:
   675  			c_type = C.TBYTE
   676  			value := value.([]uint8)
   677  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   678  			c_ptr := unsafe.Pointer(slice.Data)
   679  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   680  
   681  		case reflect.Uint16:
   682  			c_type = C.TUSHORT
   683  			value := value.([]uint16)
   684  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   685  			c_ptr := unsafe.Pointer(slice.Data)
   686  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   687  
   688  		case reflect.Uint32:
   689  			c_type = C.TUINT
   690  			value := value.([]uint32)
   691  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   692  			c_ptr := unsafe.Pointer(slice.Data)
   693  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   694  
   695  		case reflect.Uint64:
   696  			c_type = C.TULONG
   697  			value := value.([]uint64)
   698  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   699  			c_ptr := unsafe.Pointer(slice.Data)
   700  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   701  
   702  		case reflect.Uint:
   703  			c_type = C.TULONG
   704  			value := value.([]uint)
   705  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   706  			c_ptr := unsafe.Pointer(slice.Data)
   707  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   708  
   709  		case reflect.Int8:
   710  			c_type = C.TSBYTE
   711  			value := value.([]int8)
   712  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   713  			c_ptr := unsafe.Pointer(slice.Data)
   714  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   715  
   716  		case reflect.Int16:
   717  			c_type = C.TSHORT
   718  			value := value.([]int16)
   719  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   720  			c_ptr := unsafe.Pointer(slice.Data)
   721  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   722  
   723  		case reflect.Int32:
   724  			c_type = C.TINT
   725  			value := value.([]int32)
   726  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   727  			c_ptr := unsafe.Pointer(slice.Data)
   728  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   729  
   730  		case reflect.Int64:
   731  			c_type = C.TLONG
   732  			value := value.([]int64)
   733  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   734  			c_ptr := unsafe.Pointer(slice.Data)
   735  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   736  
   737  		case reflect.Int:
   738  			c_type = C.TLONG
   739  			value := value.([]int)
   740  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   741  			c_ptr := unsafe.Pointer(slice.Data)
   742  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   743  
   744  		case reflect.Float32:
   745  			c_type = C.TFLOAT
   746  			value := value.([]float32)
   747  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   748  			c_ptr := unsafe.Pointer(slice.Data)
   749  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   750  
   751  		case reflect.Float64:
   752  			c_type = C.TDOUBLE
   753  			value := value.([]float64)
   754  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   755  			c_ptr := unsafe.Pointer(slice.Data)
   756  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   757  
   758  		case reflect.Complex64:
   759  			c_type = C.TCOMPLEX
   760  			value := value.([]complex64)
   761  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value))) // FIXME: assume same bin-layout
   762  			c_ptr := unsafe.Pointer(slice.Data)
   763  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   764  
   765  		case reflect.Complex128:
   766  			c_type = C.TDBLCOMPLEX
   767  			value := value.([]complex128)
   768  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value))) // FIXME: assume same bin-layout
   769  			c_ptr := unsafe.Pointer(slice.Data)
   770  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   771  		default:
   772  			panic(fmt.Errorf("unhandled type '%T'", value))
   773  		}
   774  
   775  	case reflect.Array:
   776  		//rp := reflect.PtrTo(rv.Type())
   777  		c_ptr := unsafe.Pointer(rv.Pointer())
   778  		c_len := C.LONGLONG(rt.Len())
   779  
   780  		switch rt.Elem().Kind() {
   781  		case reflect.Bool:
   782  			c_type = C.TLOGICAL
   783  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   784  
   785  		case reflect.Uint8:
   786  			c_type = C.TBYTE
   787  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   788  
   789  		case reflect.Uint16:
   790  			c_type = C.TUSHORT
   791  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   792  
   793  		case reflect.Uint32:
   794  			c_type = C.TUINT
   795  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   796  
   797  		case reflect.Uint64:
   798  			c_type = C.TULONG
   799  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   800  
   801  		case reflect.Uint:
   802  			c_type = C.TULONG
   803  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   804  
   805  		case reflect.Int8:
   806  			c_type = C.TSBYTE
   807  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   808  
   809  		case reflect.Int16:
   810  			c_type = C.TSHORT
   811  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   812  
   813  		case reflect.Int32:
   814  			c_type = C.TINT
   815  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   816  
   817  		case reflect.Int64:
   818  			c_type = C.TLONG
   819  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   820  
   821  		case reflect.Int:
   822  			c_type = C.TLONG
   823  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   824  
   825  		case reflect.Float32:
   826  			c_type = C.TFLOAT
   827  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   828  
   829  		case reflect.Float64:
   830  			c_type = C.TDOUBLE
   831  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   832  
   833  		case reflect.Complex64:
   834  			c_type = C.TCOMPLEX
   835  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   836  
   837  		case reflect.Complex128:
   838  			c_type = C.TDBLCOMPLEX
   839  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   840  		default:
   841  			panic(fmt.Errorf("unhandled type '%T'", value))
   842  		}
   843  
   844  	default:
   845  		panic(fmt.Errorf("unhandled type '%T' (%v)", value, rt.Kind()))
   846  	}
   847  
   848  	if c_status > 0 {
   849  		err = to_err(c_status)
   850  	}
   851  
   852  	return err
   853  }
   854  
   855  // EOF