github.com/astrogo/cfitsio@v0.1.0/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  	Type    TypeCode
    28  	Len     int   // repeat. if <= 1: scalar
    29  	Value   Value // value at current row
    30  }
    31  
    32  // inferFormat infers the FITS format associated with a Column, according to its HDUType and Go type.
    33  func (col *Column) inferFormat(htype HDUType) error {
    34  	var err error
    35  	if col.Format != "" {
    36  		return nil
    37  	}
    38  
    39  	str := gotype2FITS(col.Value, htype)
    40  	if str == "" {
    41  		return fmt.Errorf("cfitsio: %v can not handle [%T]", htype, col.Value)
    42  	}
    43  	col.Format = str
    44  	return err
    45  }
    46  
    47  // read reads the value at column number icol and row irow, into ptr.
    48  // icol and irow are 0-based indices.
    49  func (col *Column) read(f *File, icol int, irow int64, ptr interface{}) error {
    50  	var err error
    51  
    52  	c_type := C.int(0)
    53  	c_icol := C.int(icol + 1)      // 0-based to 1-based index
    54  	c_irow := C.LONGLONG(irow + 1) // 0-based to 1-based index
    55  
    56  	c_len := C.LONGLONG(col.Len)
    57  	if col.Len <= 1 {
    58  		c_len = 1
    59  	}
    60  
    61  	var value interface{}
    62  	rv := reflect.Indirect(reflect.ValueOf(ptr))
    63  	rt := reflect.TypeOf(rv.Interface())
    64  
    65  	decode := func(c_type C.int, c_len C.LONGLONG, rt reflect.Type, scalar bool) (interface{}, error) {
    66  		var value interface{}
    67  		c_status := C.int(0)
    68  		c_anynul := C.int(0)
    69  
    70  		switch rt.Kind() {
    71  		case reflect.Bool:
    72  			c_type = C.TLOGICAL
    73  			v := make([]C.char, int(c_len), int(c_len))
    74  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
    75  			c_ptr := unsafe.Pointer(slice.Data)
    76  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
    77  			if scalar {
    78  				value = v[0] == 1
    79  			} else {
    80  				vv := make([]bool, len(v), len(v))
    81  				for ci, cv := range v {
    82  					vv[ci] = cv == 1
    83  				}
    84  				value = vv
    85  			}
    86  
    87  		case reflect.Uint8:
    88  			c_type = C.TBYTE
    89  			v := make([]uint8, int(c_len), int(c_len))
    90  			value = v
    91  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
    92  			c_ptr := unsafe.Pointer(slice.Data)
    93  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
    94  			if scalar {
    95  				value = v[0]
    96  			}
    97  
    98  		case reflect.Uint16:
    99  			c_type = C.TUSHORT
   100  			v := make([]uint16, int(c_len), int(c_len))
   101  			value = v
   102  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   103  			c_ptr := unsafe.Pointer(slice.Data)
   104  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   105  			if scalar {
   106  				value = v[0]
   107  			}
   108  
   109  		case reflect.Uint32:
   110  			c_type = C.TUINT
   111  			v := make([]uint32, int(c_len), int(c_len))
   112  			value = v
   113  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   114  			c_ptr := unsafe.Pointer(slice.Data)
   115  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   116  			if scalar {
   117  				value = v[0]
   118  			}
   119  
   120  		case reflect.Uint64:
   121  			c_type = C.TULONG
   122  			v := make([]uint64, int(c_len), int(c_len))
   123  			value = v
   124  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   125  			c_ptr := unsafe.Pointer(slice.Data)
   126  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   127  			if scalar {
   128  				value = v[0]
   129  			}
   130  
   131  		case reflect.Uint:
   132  			c_type = C.TULONG
   133  			v := make([]uint, int(c_len), int(c_len))
   134  			value = v
   135  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   136  			c_ptr := unsafe.Pointer(slice.Data)
   137  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   138  			if scalar {
   139  				value = v[0]
   140  			}
   141  
   142  		case reflect.Int8:
   143  			c_type = C.TSBYTE
   144  			v := make([]int8, int(c_len), int(c_len))
   145  			value = v
   146  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   147  			c_ptr := unsafe.Pointer(slice.Data)
   148  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   149  			if scalar {
   150  				value = v[0]
   151  			}
   152  
   153  		case reflect.Int16:
   154  			c_type = C.TSHORT
   155  			v := make([]int16, int(c_len), int(c_len))
   156  			value = v
   157  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   158  			c_ptr := unsafe.Pointer(slice.Data)
   159  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   160  			if scalar {
   161  				value = v[0]
   162  			}
   163  
   164  		case reflect.Int32:
   165  			c_type = C.TINT
   166  			v := make([]int32, int(c_len), int(c_len))
   167  			value = v
   168  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   169  			c_ptr := unsafe.Pointer(slice.Data)
   170  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   171  			if scalar {
   172  				value = v[0]
   173  			}
   174  
   175  		case reflect.Int64:
   176  			c_type = C.TLONG
   177  			v := make([]int64, int(c_len), int(c_len))
   178  			value = v
   179  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   180  			c_ptr := unsafe.Pointer(slice.Data)
   181  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   182  			if scalar {
   183  				value = v[0]
   184  			}
   185  
   186  		case reflect.Int:
   187  			c_type = C.TLONG
   188  			v := make([]int, int(c_len), int(c_len))
   189  			value = v
   190  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   191  			c_ptr := unsafe.Pointer(slice.Data)
   192  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   193  			if scalar {
   194  				value = v[0]
   195  			}
   196  
   197  		case reflect.Float32:
   198  			c_type = C.TFLOAT
   199  			v := make([]float32, int(c_len), int(c_len))
   200  			value = v
   201  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   202  			c_ptr := unsafe.Pointer(slice.Data)
   203  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   204  			if scalar {
   205  				value = v[0]
   206  			}
   207  
   208  		case reflect.Float64:
   209  			c_type = C.TDOUBLE
   210  			v := make([]float64, int(c_len), int(c_len))
   211  			value = v
   212  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   213  			c_ptr := unsafe.Pointer(slice.Data)
   214  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   215  			if scalar {
   216  				value = v[0]
   217  			}
   218  
   219  		case reflect.Complex64:
   220  			c_type = C.TCOMPLEX
   221  			v := make([]complex64, int(c_len), int(c_len)) // FIXME: assume same binary layout
   222  			value = v
   223  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   224  			c_ptr := unsafe.Pointer(slice.Data)
   225  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   226  			if scalar {
   227  				value = v[0]
   228  			}
   229  
   230  		case reflect.Complex128:
   231  			c_type = C.TDBLCOMPLEX
   232  			v := make([]complex128, int(c_len), int(c_len)) // FIXME: assume same binary layout
   233  			value = v
   234  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&v)))
   235  			c_ptr := unsafe.Pointer(slice.Data)
   236  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, c_len, nil, c_ptr, &c_anynul, &c_status)
   237  			if scalar {
   238  				value = v[0]
   239  			}
   240  
   241  		case reflect.String:
   242  			c_type = C.TSTRING
   243  			// FIXME: get correct maximum size from card
   244  			c_value := C.CStringN(C.FLEN_FILENAME)
   245  			defer C.free(unsafe.Pointer(c_value))
   246  			c_ptr := unsafe.Pointer(&c_value)
   247  			C.fits_read_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, c_ptr, &c_anynul, &c_status)
   248  			value = C.GoString(c_value)
   249  
   250  		default:
   251  			return value, fmt.Errorf("cfitsio: invalid type [%v]", rt)
   252  		}
   253  
   254  		if c_status > 0 {
   255  			err = to_err(c_status)
   256  			return value, err
   257  		}
   258  		return value, nil
   259  	}
   260  
   261  	switch rt.Kind() {
   262  
   263  	case reflect.Slice:
   264  		c_len := C.long(0)
   265  		if col.Type < 0 {
   266  			c_off := C.long(0)
   267  			c_status := C.int(0)
   268  			C.fits_read_descript(f.c, c_icol, c_irow, &c_len, &c_off, &c_status)
   269  			if c_status > 0 {
   270  				err = to_err(c_status)
   271  				return err
   272  			}
   273  		} else {
   274  			c_len = C.long(col.Len)
   275  		}
   276  		scalar := false
   277  		value, err = decode(c_type, C.LONGLONG(c_len), rt.Elem(), scalar)
   278  
   279  		rv.Set(reflect.ValueOf(value))
   280  		col.Value = rv.Interface()
   281  
   282  	case reflect.Array:
   283  		c_len := C.long(rt.Len())
   284  		scalar := false
   285  		value, err = decode(c_type, C.LONGLONG(c_len), rt.Elem(), scalar)
   286  
   287  		// FIXME: unnecessary copy
   288  		array := reflect.New(rt).Elem()
   289  		reflect.Copy(array, reflect.ValueOf(value))
   290  		rv.Set(array)
   291  		col.Value = rv.Interface()
   292  
   293  	case reflect.Bool,
   294  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   295  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   296  		reflect.Float32, reflect.Float64,
   297  		reflect.Complex64, reflect.Complex128,
   298  		reflect.String:
   299  
   300  		scalar := true
   301  		value, err = decode(c_type, C.LONGLONG(c_len), rt, scalar)
   302  
   303  		rv.Set(reflect.ValueOf(value))
   304  		col.Value = rv.Interface()
   305  
   306  	default:
   307  		return fmt.Errorf("cfitsio: invalid type [%v]", rt)
   308  	}
   309  
   310  	return err
   311  }
   312  
   313  // write writes the current value of this Column into file f at column icol and row irow.
   314  // icol and irow are 0-based indices.
   315  func (col *Column) write(f *File, icol int, irow int64, value interface{}) error {
   316  	var err error
   317  
   318  	c_type := C.int(0)
   319  	c_icol := C.int(icol + 1)      // 0-based to 1-based index
   320  	c_irow := C.LONGLONG(irow + 1) // 0-based to 1-based index
   321  	c_status := C.int(0)
   322  
   323  	rv := reflect.ValueOf(value)
   324  	rt := reflect.TypeOf(value)
   325  
   326  	switch rt.Kind() {
   327  	case reflect.Bool:
   328  		c_type = C.TLOGICAL
   329  		c_value := C.char(0) // 'F'
   330  		if value.(bool) {
   331  			c_value = 1
   332  		}
   333  		c_ptr := unsafe.Pointer(&c_value)
   334  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   335  
   336  	case reflect.Uint8:
   337  		c_type = C.TBYTE
   338  		c_value := C.char(value.(byte))
   339  		c_ptr := unsafe.Pointer(&c_value)
   340  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   341  
   342  	case reflect.Uint16:
   343  		c_type = C.TUSHORT
   344  		c_value := C.ushort(value.(uint16))
   345  		c_ptr := unsafe.Pointer(&c_value)
   346  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   347  
   348  	case reflect.Uint32:
   349  		c_type = C.TUINT
   350  		c_value := C.uint(value.(uint32))
   351  		c_ptr := unsafe.Pointer(&c_value)
   352  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   353  
   354  	case reflect.Uint64:
   355  		c_type = C.TULONG
   356  		c_value := C.ulong(value.(uint64))
   357  		c_ptr := unsafe.Pointer(&c_value)
   358  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   359  
   360  	case reflect.Uint:
   361  		c_type = C.TULONG
   362  		c_value := C.ulong(value.(uint))
   363  		c_ptr := unsafe.Pointer(&c_value)
   364  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   365  
   366  	case reflect.Int8:
   367  		c_type = C.TSBYTE
   368  		c_value := C.char(value.(int8))
   369  		c_ptr := unsafe.Pointer(&c_value)
   370  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   371  
   372  	case reflect.Int16:
   373  		c_type = C.TSHORT
   374  		c_value := C.short(value.(int16))
   375  		c_ptr := unsafe.Pointer(&c_value)
   376  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   377  
   378  	case reflect.Int32:
   379  		c_type = C.TINT
   380  		c_value := C.int(value.(int32))
   381  		c_ptr := unsafe.Pointer(&c_value)
   382  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   383  
   384  	case reflect.Int64:
   385  		c_type = C.TLONG
   386  		c_value := C.long(value.(int64))
   387  		c_ptr := unsafe.Pointer(&c_value)
   388  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   389  
   390  	case reflect.Int:
   391  		c_type = C.TLONG
   392  		c_value := C.long(value.(int))
   393  		c_ptr := unsafe.Pointer(&c_value)
   394  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   395  
   396  	case reflect.Float32:
   397  		c_type = C.TFLOAT
   398  		c_value := C.float(value.(float32))
   399  		c_ptr := unsafe.Pointer(&c_value)
   400  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   401  
   402  	case reflect.Float64:
   403  		c_type = C.TDOUBLE
   404  		c_value := C.double(value.(float64))
   405  		c_ptr := unsafe.Pointer(&c_value)
   406  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   407  
   408  	case reflect.Complex64:
   409  		c_type = C.TCOMPLEX
   410  		value := value.(complex64)
   411  		c_ptr := unsafe.Pointer(&value) // FIXME: assumes same memory layout
   412  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   413  
   414  	case reflect.Complex128:
   415  		c_type = C.TDBLCOMPLEX
   416  		value := value.(complex128)
   417  		c_ptr := unsafe.Pointer(&value) // FIXME: assumes same memory layout
   418  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   419  
   420  	case reflect.String:
   421  		c_type = C.TSTRING
   422  		c_value := C.CString(value.(string))
   423  		defer C.free(unsafe.Pointer(c_value))
   424  		c_ptr := unsafe.Pointer(&c_value)
   425  		C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, 1, c_ptr, &c_status)
   426  
   427  	case reflect.Slice:
   428  		switch rt.Elem().Kind() {
   429  		case reflect.Bool:
   430  			c_type = C.TLOGICAL
   431  			value := value.([]bool)
   432  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   433  			c_ptr := unsafe.Pointer(slice.Data)
   434  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   435  
   436  		case reflect.Uint8:
   437  			c_type = C.TBYTE
   438  			value := value.([]uint8)
   439  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   440  			c_ptr := unsafe.Pointer(slice.Data)
   441  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   442  
   443  		case reflect.Uint16:
   444  			c_type = C.TUSHORT
   445  			value := value.([]uint16)
   446  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   447  			c_ptr := unsafe.Pointer(slice.Data)
   448  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   449  
   450  		case reflect.Uint32:
   451  			c_type = C.TUINT
   452  			value := value.([]uint32)
   453  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   454  			c_ptr := unsafe.Pointer(slice.Data)
   455  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   456  
   457  		case reflect.Uint64:
   458  			c_type = C.TULONG
   459  			value := value.([]uint64)
   460  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   461  			c_ptr := unsafe.Pointer(slice.Data)
   462  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   463  
   464  		case reflect.Uint:
   465  			c_type = C.TULONG
   466  			value := value.([]uint)
   467  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   468  			c_ptr := unsafe.Pointer(slice.Data)
   469  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   470  
   471  		case reflect.Int8:
   472  			c_type = C.TSBYTE
   473  			value := value.([]int8)
   474  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   475  			c_ptr := unsafe.Pointer(slice.Data)
   476  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   477  
   478  		case reflect.Int16:
   479  			c_type = C.TSHORT
   480  			value := value.([]int16)
   481  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   482  			c_ptr := unsafe.Pointer(slice.Data)
   483  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   484  
   485  		case reflect.Int32:
   486  			c_type = C.TINT
   487  			value := value.([]int32)
   488  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   489  			c_ptr := unsafe.Pointer(slice.Data)
   490  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   491  
   492  		case reflect.Int64:
   493  			c_type = C.TLONG
   494  			value := value.([]int64)
   495  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   496  			c_ptr := unsafe.Pointer(slice.Data)
   497  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   498  
   499  		case reflect.Int:
   500  			c_type = C.TLONG
   501  			value := value.([]int)
   502  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   503  			c_ptr := unsafe.Pointer(slice.Data)
   504  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   505  
   506  		case reflect.Float32:
   507  			c_type = C.TFLOAT
   508  			value := value.([]float32)
   509  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   510  			c_ptr := unsafe.Pointer(slice.Data)
   511  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   512  
   513  		case reflect.Float64:
   514  			c_type = C.TDOUBLE
   515  			value := value.([]float64)
   516  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value)))
   517  			c_ptr := unsafe.Pointer(slice.Data)
   518  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   519  
   520  		case reflect.Complex64:
   521  			c_type = C.TCOMPLEX
   522  			value := value.([]complex64)
   523  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value))) // FIXME: assume same bin-layout
   524  			c_ptr := unsafe.Pointer(slice.Data)
   525  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   526  
   527  		case reflect.Complex128:
   528  			c_type = C.TDBLCOMPLEX
   529  			value := value.([]complex128)
   530  			slice := (*reflect.SliceHeader)((unsafe.Pointer(&value))) // FIXME: assume same bin-layout
   531  			c_ptr := unsafe.Pointer(slice.Data)
   532  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, C.LONGLONG(slice.Len), c_ptr, &c_status)
   533  		default:
   534  			panic(fmt.Errorf("unhandled type '%T'", value))
   535  		}
   536  
   537  	case reflect.Array:
   538  
   539  		// FIXME: unnecessary copy
   540  		arr := reflect.New(rv.Type()).Elem()
   541  		reflect.Copy(arr, rv)
   542  		ptr := arr.Addr()
   543  		c_ptr := unsafe.Pointer(ptr.Pointer())
   544  		c_len := C.LONGLONG(rt.Len())
   545  
   546  		switch rt.Elem().Kind() {
   547  		case reflect.Bool:
   548  			c_type = C.TLOGICAL
   549  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   550  
   551  		case reflect.Uint8:
   552  			c_type = C.TBYTE
   553  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   554  
   555  		case reflect.Uint16:
   556  			c_type = C.TUSHORT
   557  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   558  
   559  		case reflect.Uint32:
   560  			c_type = C.TUINT
   561  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   562  
   563  		case reflect.Uint64:
   564  			c_type = C.TULONG
   565  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   566  
   567  		case reflect.Uint:
   568  			c_type = C.TULONG
   569  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   570  
   571  		case reflect.Int8:
   572  			c_type = C.TSBYTE
   573  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   574  
   575  		case reflect.Int16:
   576  			c_type = C.TSHORT
   577  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   578  
   579  		case reflect.Int32:
   580  			c_type = C.TINT
   581  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   582  
   583  		case reflect.Int64:
   584  			c_type = C.TLONG
   585  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   586  
   587  		case reflect.Int:
   588  			c_type = C.TLONG
   589  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   590  
   591  		case reflect.Float32:
   592  			c_type = C.TFLOAT
   593  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   594  
   595  		case reflect.Float64:
   596  			c_type = C.TDOUBLE
   597  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   598  
   599  		case reflect.Complex64:
   600  			c_type = C.TCOMPLEX
   601  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   602  
   603  		case reflect.Complex128:
   604  			c_type = C.TDBLCOMPLEX
   605  			C.fits_write_col(f.c, c_type, c_icol, c_irow, 1, c_len, c_ptr, &c_status)
   606  		default:
   607  			panic(fmt.Errorf("unhandled type '%T'", value))
   608  		}
   609  
   610  	default:
   611  		panic(fmt.Errorf("unhandled type '%T' (%v)", value, rt.Kind()))
   612  	}
   613  
   614  	if c_status > 0 {
   615  		err = to_err(c_status)
   616  	}
   617  
   618  	return err
   619  }
   620  
   621  // EOF