diff --git a/README.md b/README.md index db26361..df686b1 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ Roger allows variables to be defined within an R session from Go. Currently the - string and string arrays - byte arrays - - double arrays - - int arrays + - doubles and double arrays + - ints and int arrays For examples see assignment_test.go. diff --git a/assign/factory.go b/assign/factory.go index c541f72..ce0311d 100644 --- a/assign/factory.go +++ b/assign/factory.go @@ -15,6 +15,10 @@ func Assign(symbol string, value interface{}) ([]byte, error) { return assignByteArray(symbol, value.([]byte)) case string: return assignStr(symbol, value.(string)) + case int32: + return assignInt(symbol, value.(int32)) + case float64: + return assignDouble(symbol, value.(float64)) default: return nil, errors.New("session assign: type is not supported") } diff --git a/assign/xt-double.go b/assign/xt-double.go new file mode 100644 index 0000000..ca5b7bb --- /dev/null +++ b/assign/xt-double.go @@ -0,0 +1,45 @@ +package assign + +import ( + "math" + + "github.com/senseyeio/roger/constants" +) + +func assignDouble(symbol string, value float64) ([]byte, error) { + rl := 8 + + symn := []byte(symbol) + sl := len(symn) + 1 + if (sl & 3) > 0 { + sl = (sl & 0xfffffc) + 4 + } + + var rq []byte + + shl := GetHeaderLength(constants.DtString, sl) + sextHeader := GetHeaderLength(constants.DataType(constants.XtDouble), rl) + rhl := GetHeaderLength(constants.DtSexp, rl+sextHeader) + + rq = make([]byte, sl+rl+shl+rhl+sextHeader) + + ic := 0 + for ; ic < len(symn); ic++ { + rq[ic+shl] = symn[ic] + } + for ic < sl { + rq[ic+shl] = 0 + ic++ + } + + setHdrOffset(constants.DtString, sl, rq, 0) + setHdrOffset(constants.DtSexp, rl+sextHeader, rq, sl+shl) + + off := sl + shl + rhl + setHdrOffset(constants.DataType(constants.XtDouble), rl, rq, off) + off += sextHeader + + setLong(int64(math.Float64bits(value)), rq, off) + + return rq, nil +} diff --git a/assign/xt-int.go b/assign/xt-int.go new file mode 100644 index 0000000..17c59af --- /dev/null +++ b/assign/xt-int.go @@ -0,0 +1,43 @@ +package assign + +import ( + "github.com/senseyeio/roger/constants" +) + +func assignInt(symbol string, value int32) ([]byte, error) { + rl := 4 + + symn := []byte(symbol) + sl := len(symn) + 1 + if (sl & 3) > 0 { + sl = (sl & 0xfffffc) + 4 + } + + var rq []byte + + shl := GetHeaderLength(constants.DtString, sl) + sextHeader := GetHeaderLength(constants.DataType(constants.XtInt), rl) + rhl := GetHeaderLength(constants.DtSexp, rl+sextHeader) + + rq = make([]byte, sl+rl+shl+rhl+sextHeader) + + ic := 0 + for ; ic < len(symn); ic++ { + rq[ic+shl] = symn[ic] + } + for ic < sl { + rq[ic+shl] = 0 + ic++ + } + + setHdrOffset(constants.DtString, sl, rq, 0) + setHdrOffset(constants.DtSexp, rl+sextHeader, rq, sl+shl) + + off := sl + shl + rhl + setHdrOffset(constants.DataType(constants.XtInt), rl, rq, off) + off += sextHeader + + SetInt(int(value), rq, off) + + return rq, nil +} diff --git a/assignment_test.go b/assignment_test.go index e360fd6..60cf5cc 100644 --- a/assignment_test.go +++ b/assignment_test.go @@ -22,6 +22,14 @@ func TestIntArrayAssignment(t *testing.T) { checkAssignment(t, []int32{1, 2, 3, 4, 5}) } +func TestIntAssignment(t *testing.T) { + checkAssignment(t, int32(100)) +} + +func TestDoubleAssignment(t *testing.T) { + checkAssignment(t, float64(123.4)) +} + func TestFloatArrayAssignment(t *testing.T) { checkAssignment(t, []float64{1.1, 2.2, 3.3, 4.4, 5.5}) } diff --git a/constants/expressions.go b/constants/expressions.go index 46e715f..a89beb4 100644 --- a/constants/expressions.go +++ b/constants/expressions.go @@ -5,6 +5,7 @@ type ExpressionType int const ( XtNull ExpressionType = 0 /* P data: [0] */ XtInt ExpressionType = 1 /* P data: [4]int */ + XtDouble ExpressionType = 2 /* - data: [8]double */ XtString ExpressionType = 3 /* P data: [n]char null-term. strg. */ XtLang ExpressionType = 4 /* - */ XtS4 ExpressionType = 7 /* P data: [0] */