github.com/mattn/anko@v0.1.10/vm/vmToX.go (about)

     1  package vm
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strconv"
     8  	"strings"
     9  )
    10  
    11  // toString converts all reflect.Value-s into string.
    12  func toString(v reflect.Value) string {
    13  	if v.Kind() == reflect.Interface && !v.IsNil() {
    14  		v = v.Elem()
    15  	}
    16  	if v.Kind() == reflect.Ptr {
    17  		v = v.Elem()
    18  	}
    19  	if v.Kind() == reflect.String {
    20  		return v.String()
    21  	}
    22  	return fmt.Sprint(v.Interface())
    23  }
    24  
    25  // toBool converts all reflect.Value-s into bool.
    26  func toBool(v reflect.Value) bool {
    27  	b, _ := tryToBool(v)
    28  	return b
    29  }
    30  
    31  // tryToBool attempts to convert the value 'v' to a boolean, returning
    32  // an error if it cannot. When converting a string, the function returns
    33  // true if the string nonempty and does not satisfy the condition for false
    34  // with parseBool https://golang.org/pkg/strconv/#ParseBool
    35  // and is not 0.0
    36  func tryToBool(v reflect.Value) (bool, error) {
    37  	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
    38  		v = v.Elem()
    39  	}
    40  	switch v.Kind() {
    41  	case reflect.Float64, reflect.Float32:
    42  		return v.Float() != 0, nil
    43  	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
    44  		return v.Int() != 0, nil
    45  	case reflect.Bool:
    46  		return v.Bool(), nil
    47  	case reflect.String:
    48  		if v.Len() == 0 {
    49  			return false, nil
    50  		}
    51  
    52  		s := v.String()
    53  		if b, err := strconv.ParseBool(s); err == nil && !b {
    54  			return false, nil
    55  		}
    56  
    57  		if f, err := tryToFloat64(v); err == nil && f == 0 {
    58  			return false, nil
    59  		}
    60  		return true, nil
    61  	case reflect.Slice, reflect.Map:
    62  		if v.Len() > 0 {
    63  			return true, nil
    64  		}
    65  		return false, nil
    66  	}
    67  	return false, errors.New("unknown type")
    68  }
    69  
    70  // toFloat64 converts all reflect.Value-s into float64.
    71  func toFloat64(v reflect.Value) float64 {
    72  	f, _ := tryToFloat64(v)
    73  	return f
    74  }
    75  
    76  // tryToFloat64 attempts to convert a value to a float64.
    77  // If it cannot (in the case of a non-numeric string, a struct, etc.)
    78  // it returns 0.0 and an error.
    79  func tryToFloat64(v reflect.Value) (float64, error) {
    80  	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
    81  		v = v.Elem()
    82  	}
    83  	switch v.Kind() {
    84  	case reflect.Float64, reflect.Float32:
    85  		return v.Float(), nil
    86  	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
    87  		return float64(v.Int()), nil
    88  	case reflect.Bool:
    89  		if v.Bool() {
    90  			return 1, nil
    91  		}
    92  		return 0, nil
    93  	case reflect.String:
    94  		f, err := strconv.ParseFloat(v.String(), 64)
    95  		if err == nil {
    96  			return f, nil
    97  		}
    98  	}
    99  	return 0.0, errors.New("couldn't convert to a float64")
   100  }
   101  
   102  // toInt64 converts all reflect.Value-s into int64.
   103  func toInt64(v reflect.Value) int64 {
   104  	i, _ := tryToInt64(v)
   105  	return i
   106  }
   107  
   108  // tryToInt64 attempts to convert a value to an int64.
   109  // If it cannot (in the case of a non-numeric string, a struct, etc.)
   110  // it returns 0 and an error.
   111  func tryToInt64(v reflect.Value) (int64, error) {
   112  	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
   113  		v = v.Elem()
   114  	}
   115  	switch v.Kind() {
   116  	case reflect.Float64, reflect.Float32:
   117  		return int64(v.Float()), nil
   118  	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
   119  		return v.Int(), nil
   120  	case reflect.Bool:
   121  		if v.Bool() {
   122  			return 1, nil
   123  		}
   124  		return 0, nil
   125  	case reflect.String:
   126  		s := v.String()
   127  		var i int64
   128  		var err error
   129  		if strings.HasPrefix(s, "0x") {
   130  			i, err = strconv.ParseInt(s, 16, 64)
   131  		} else {
   132  			i, err = strconv.ParseInt(s, 10, 64)
   133  		}
   134  		if err == nil {
   135  			return i, nil
   136  		}
   137  	}
   138  	return 0, errors.New("couldn't convert to integer")
   139  }
   140  
   141  // toInt converts all reflect.Value-s into int.
   142  func toInt(v reflect.Value) int {
   143  	i, _ := tryToInt(v)
   144  	return i
   145  }
   146  
   147  // tryToInt attempts to convert a value to an int.
   148  // If it cannot (in the case of a non-numeric string, a struct, etc.)
   149  // it returns 0 and an error.
   150  func tryToInt(v reflect.Value) (int, error) {
   151  	if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
   152  		v = v.Elem()
   153  	}
   154  	switch v.Kind() {
   155  	case reflect.Float64, reflect.Float32:
   156  		return int(v.Float()), nil
   157  	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
   158  		return int(v.Int()), nil
   159  	case reflect.Bool:
   160  		if v.Bool() {
   161  			return 1, nil
   162  		}
   163  		return 0, nil
   164  	case reflect.String:
   165  		s := v.String()
   166  		var i int64
   167  		var err error
   168  		if strings.HasPrefix(s, "0x") {
   169  			i, err = strconv.ParseInt(s, 16, 64)
   170  		} else {
   171  			i, err = strconv.ParseInt(s, 10, 64)
   172  		}
   173  		if err == nil {
   174  			return int(i), nil
   175  		}
   176  	}
   177  	return 0, errors.New("couldn't convert to integer")
   178  }