OSDN Git Service

Update Go library to last weekly.
[pf3gnuchains/gcc-fork.git] / libgo / go / exp / sql / convert.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Type conversions for Scan.
6
7 package sql
8
9 import (
10         "fmt"
11         "os"
12         "reflect"
13         "strconv"
14 )
15
16 // convertAssign copies to dest the value in src, converting it if possible.
17 // An error is returned if the copy would result in loss of information.
18 // dest should be a pointer type.
19 func convertAssign(dest, src interface{}) os.Error {
20         // Common cases, without reflect.  Fall through.
21         switch s := src.(type) {
22         case string:
23                 switch d := dest.(type) {
24                 case *string:
25                         *d = s
26                         return nil
27                 }
28         case []byte:
29                 switch d := dest.(type) {
30                 case *string:
31                         *d = string(s)
32                         return nil
33                 case *[]byte:
34                         *d = s
35                         return nil
36                 }
37         }
38
39         sv := reflect.ValueOf(src)
40
41         switch d := dest.(type) {
42         case *string:
43                 switch sv.Kind() {
44                 case reflect.Bool,
45                         reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
46                         reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
47                         reflect.Float32, reflect.Float64:
48                         *d = fmt.Sprintf("%v", src)
49                         return nil
50                 }
51         }
52
53         if scanner, ok := dest.(ScannerInto); ok {
54                 return scanner.ScanInto(src)
55         }
56
57         dpv := reflect.ValueOf(dest)
58         if dpv.Kind() != reflect.Ptr {
59                 return os.NewError("destination not a pointer")
60         }
61
62         dv := reflect.Indirect(dpv)
63         if dv.Kind() == sv.Kind() {
64                 dv.Set(sv)
65                 return nil
66         }
67
68         switch dv.Kind() {
69         case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
70                 if s, ok := asString(src); ok {
71                         i64, err := strconv.Atoi64(s)
72                         if err != nil {
73                                 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
74                         }
75                         if dv.OverflowInt(i64) {
76                                 return fmt.Errorf("string %q overflows %s", s, dv.Kind())
77                         }
78                         dv.SetInt(i64)
79                         return nil
80                 }
81         case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
82                 if s, ok := asString(src); ok {
83                         u64, err := strconv.Atoui64(s)
84                         if err != nil {
85                                 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
86                         }
87                         if dv.OverflowUint(u64) {
88                                 return fmt.Errorf("string %q overflows %s", s, dv.Kind())
89                         }
90                         dv.SetUint(u64)
91                         return nil
92                 }
93         }
94
95         return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
96 }
97
98 func asString(src interface{}) (s string, ok bool) {
99         switch v := src.(type) {
100         case string:
101                 return v, true
102         case []byte:
103                 return string(v), true
104         }
105         return "", false
106 }