Repository: lucy-clownfish
Updated Branches:
  refs/heads/master 6dc5deb06 -> a94a2ec57


Better nil-checking in GoToClownfish.

It's not enough to check nil for the supplied `interface{}` value.  You
also have to check nil for certain Go types inside a type switch, in
case the type portion of the interface value is non-nil but the value
portion is nil.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/770e4ce0
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/770e4ce0
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/770e4ce0

Branch: refs/heads/master
Commit: 770e4ce096a4f84efd94d2b60001b0dbb42cdfb7
Parents: 6dc5deb
Author: Marvin Humphrey <[email protected]>
Authored: Tue Oct 6 18:45:47 2015 -0700
Committer: Marvin Humphrey <[email protected]>
Committed: Tue Oct 6 18:45:47 2015 -0700

----------------------------------------------------------------------
 runtime/go/clownfish/clownfish.go | 60 ++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/770e4ce0/runtime/go/clownfish/clownfish.go
----------------------------------------------------------------------
diff --git a/runtime/go/clownfish/clownfish.go 
b/runtime/go/clownfish/clownfish.go
index 6b4dc28..a881cda 100644
--- a/runtime/go/clownfish/clownfish.go
+++ b/runtime/go/clownfish/clownfish.go
@@ -343,12 +343,18 @@ func goToString(value interface{}, nullable bool) 
unsafe.Pointer {
 func goToBlob(value interface{}, nullable bool) unsafe.Pointer {
        switch v := value.(type) {
        case []byte:
-               size := C.size_t(len(v))
-               var buf *C.char = nil
-               if size > 0 {
-                       buf = ((*C.char)(unsafe.Pointer(&v[0])))
+               if v == nil {
+                       if nullable {
+                               return nil
+                       }
+               } else {
+                       size := C.size_t(len(v))
+                       var buf *C.char = nil
+                       if size > 0 {
+                               buf = ((*C.char)(unsafe.Pointer(&v[0])))
+                       }
+                       return unsafe.Pointer(C.cfish_Blob_new(buf, size))
                }
-               return unsafe.Pointer(C.cfish_Blob_new(buf, size))
        case Obj:
                certifyCF(v, C.CFISH_BLOB, nullable)
                return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR())))
@@ -434,13 +440,19 @@ func goToBoolean(value interface{}, nullable bool) 
unsafe.Pointer {
 func goToVector(value interface{}, nullable bool) unsafe.Pointer {
        switch v := value.(type) {
        case []interface{}:
-               size := len(v)
-               vec := C.cfish_Vec_new(C.size_t(size))
-               for i := 0; i < size; i++ {
-                       elem := GoToClownfish(v[i], nil, true)
-                       C.CFISH_Vec_Store(vec, C.size_t(i), 
(*C.cfish_Obj)(elem))
+               if v == nil {
+                       if nullable {
+                               return nil
+                       }
+               } else {
+                       size := len(v)
+                       vec := C.cfish_Vec_new(C.size_t(size))
+                       for i := 0; i < size; i++ {
+                               elem := GoToClownfish(v[i], nil, true)
+                               C.CFISH_Vec_Store(vec, C.size_t(i), 
(*C.cfish_Obj)(elem))
+                       }
+                       return unsafe.Pointer(vec)
                }
-               return unsafe.Pointer(vec)
        case Obj:
                certifyCF(v, C.CFISH_VECTOR, nullable)
                return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR())))
@@ -452,17 +464,23 @@ func goToVector(value interface{}, nullable bool) 
unsafe.Pointer {
 func goToHash(value interface{}, nullable bool) unsafe.Pointer {
        switch v := value.(type) {
        case map[string]interface{}:
-               size := len(v)
-               hash := C.cfish_Hash_new(C.size_t(size))
-               for key, val := range v {
-                       newVal := GoToClownfish(val, nil, true)
-                       keySize := len(key)
-                       keyStr := C.CString(key)
-                   cfKey := C.cfish_Str_new_steal_utf8(keyStr, 
C.size_t(keySize))
-                       defer C.cfish_dec_refcount(unsafe.Pointer(cfKey))
-                       C.CFISH_Hash_Store(hash, cfKey, (*C.cfish_Obj)(newVal))
+               if v == nil {
+                       if nullable {
+                               return nil
+                       }
+               } else {
+                       size := len(v)
+                       hash := C.cfish_Hash_new(C.size_t(size))
+                       for key, val := range v {
+                               newVal := GoToClownfish(val, nil, true)
+                               keySize := len(key)
+                               keyStr := C.CString(key)
+                               cfKey := C.cfish_Str_new_steal_utf8(keyStr, 
C.size_t(keySize))
+                               defer 
C.cfish_dec_refcount(unsafe.Pointer(cfKey))
+                               C.CFISH_Hash_Store(hash, cfKey, 
(*C.cfish_Obj)(newVal))
+                       }
+                       return unsafe.Pointer(hash)
                }
-               return unsafe.Pointer(hash)
        case Obj:
                certifyCF(v, C.CFISH_HASH, nullable)
                return unsafe.Pointer(C.cfish_incref(unsafe.Pointer(v.TOPTR())))

Reply via email to