github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/flosch/pongo2.v3/value.go (about)

     1  package pongo2
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  type Value struct {
    11  	val  reflect.Value
    12  	safe bool // used to indicate whether a Value needs explicit escaping in the template
    13  }
    14  
    15  // Converts any given value to a pongo2.Value
    16  // Usually being used within own functions passed to a template
    17  // through a Context or within filter functions.
    18  //
    19  // Example:
    20  //     AsValue("my string")
    21  func AsValue(i interface{}) *Value {
    22  	return &Value{
    23  		val: reflect.ValueOf(i),
    24  	}
    25  }
    26  
    27  // Like AsValue, but does not apply the 'escape' filter.
    28  func AsSafeValue(i interface{}) *Value {
    29  	return &Value{
    30  		val:  reflect.ValueOf(i),
    31  		safe: true,
    32  	}
    33  }
    34  
    35  func (v *Value) getResolvedValue() reflect.Value {
    36  	if v.val.IsValid() && v.val.Kind() == reflect.Ptr {
    37  		return v.val.Elem()
    38  	}
    39  	return v.val
    40  }
    41  
    42  // Checks whether the underlying value is a string
    43  func (v *Value) IsString() bool {
    44  	return v.getResolvedValue().Kind() == reflect.String
    45  }
    46  
    47  // Checks whether the underlying value is a bool
    48  func (v *Value) IsBool() bool {
    49  	return v.getResolvedValue().Kind() == reflect.Bool
    50  }
    51  
    52  // Checks whether the underlying value is a float
    53  func (v *Value) IsFloat() bool {
    54  	return v.getResolvedValue().Kind() == reflect.Float32 ||
    55  		v.getResolvedValue().Kind() == reflect.Float64
    56  }
    57  
    58  // Checks whether the underlying value is an integer
    59  func (v *Value) IsInteger() bool {
    60  	return v.getResolvedValue().Kind() == reflect.Int ||
    61  		v.getResolvedValue().Kind() == reflect.Int8 ||
    62  		v.getResolvedValue().Kind() == reflect.Int16 ||
    63  		v.getResolvedValue().Kind() == reflect.Int32 ||
    64  		v.getResolvedValue().Kind() == reflect.Int64 ||
    65  		v.getResolvedValue().Kind() == reflect.Uint ||
    66  		v.getResolvedValue().Kind() == reflect.Uint8 ||
    67  		v.getResolvedValue().Kind() == reflect.Uint16 ||
    68  		v.getResolvedValue().Kind() == reflect.Uint32 ||
    69  		v.getResolvedValue().Kind() == reflect.Uint64
    70  }
    71  
    72  // Checks whether the underlying value is either an integer
    73  // or a float.
    74  func (v *Value) IsNumber() bool {
    75  	return v.IsInteger() || v.IsFloat()
    76  }
    77  
    78  // Checks whether the underlying value is NIL
    79  func (v *Value) IsNil() bool {
    80  	//fmt.Printf("%+v\n", v.getResolvedValue().Type().String())
    81  	return !v.getResolvedValue().IsValid()
    82  }
    83  
    84  // Returns a string for the underlying value. If this value is not
    85  // of type string, pongo2 tries to convert it. Currently the following
    86  // types for underlying values are supported:
    87  //
    88  //     1. string
    89  //     2. int/uint (any size)
    90  //     3. float (any precision)
    91  //     4. bool
    92  //     5. time.Time
    93  //     6. String() will be called on the underlying value if provided
    94  //
    95  // NIL values will lead to an empty string. Unsupported types are leading
    96  // to their respective type name.
    97  func (v *Value) String() string {
    98  	if v.IsNil() {
    99  		return ""
   100  	}
   101  
   102  	switch v.getResolvedValue().Kind() {
   103  	case reflect.String:
   104  		return v.getResolvedValue().String()
   105  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   106  		return strconv.FormatInt(v.getResolvedValue().Int(), 10)
   107  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   108  		return strconv.FormatUint(v.getResolvedValue().Uint(), 10)
   109  	case reflect.Float32, reflect.Float64:
   110  		return fmt.Sprintf("%f", v.getResolvedValue().Float())
   111  	case reflect.Bool:
   112  		if v.Bool() {
   113  			return "True"
   114  		} else {
   115  			return "False"
   116  		}
   117  	case reflect.Struct:
   118  		if t, ok := v.Interface().(fmt.Stringer); ok {
   119  			return t.String()
   120  		}
   121  	}
   122  
   123  	logf("Value.String() not implemented for type: %s\n", v.getResolvedValue().Kind().String())
   124  	return v.getResolvedValue().String()
   125  }
   126  
   127  // Returns the underlying value as an integer (converts the underlying
   128  // value, if necessary). If it's not possible to convert the underlying value,
   129  // it will return 0.
   130  func (v *Value) Integer() int {
   131  	switch v.getResolvedValue().Kind() {
   132  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   133  		return int(v.getResolvedValue().Int())
   134  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   135  		return int(v.getResolvedValue().Uint())
   136  	case reflect.Float32, reflect.Float64:
   137  		return int(v.getResolvedValue().Float())
   138  	case reflect.String:
   139  		// Try to convert from string to int (base 10)
   140  		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
   141  		if err != nil {
   142  			return 0
   143  		}
   144  		return int(f)
   145  	default:
   146  		logf("Value.Integer() not available for type: %s\n", v.getResolvedValue().Kind().String())
   147  		return 0
   148  	}
   149  }
   150  
   151  // Returns the underlying value as a float (converts the underlying
   152  // value, if necessary). If it's not possible to convert the underlying value,
   153  // it will return 0.0.
   154  func (v *Value) Float() float64 {
   155  	switch v.getResolvedValue().Kind() {
   156  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   157  		return float64(v.getResolvedValue().Int())
   158  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   159  		return float64(v.getResolvedValue().Uint())
   160  	case reflect.Float32, reflect.Float64:
   161  		return v.getResolvedValue().Float()
   162  	case reflect.String:
   163  		// Try to convert from string to float64 (base 10)
   164  		f, err := strconv.ParseFloat(v.getResolvedValue().String(), 64)
   165  		if err != nil {
   166  			return 0.0
   167  		}
   168  		return f
   169  	default:
   170  		logf("Value.Float() not available for type: %s\n", v.getResolvedValue().Kind().String())
   171  		return 0.0
   172  	}
   173  }
   174  
   175  // Returns the underlying value as bool. If the value is not bool, false
   176  // will always be returned. If you're looking for true/false-evaluation of the
   177  // underlying value, have a look on the IsTrue()-function.
   178  func (v *Value) Bool() bool {
   179  	switch v.getResolvedValue().Kind() {
   180  	case reflect.Bool:
   181  		return v.getResolvedValue().Bool()
   182  	default:
   183  		logf("Value.Bool() not available for type: %s\n", v.getResolvedValue().Kind().String())
   184  		return false
   185  	}
   186  }
   187  
   188  // Tries to evaluate the underlying value the Pythonic-way:
   189  //
   190  // Returns TRUE in one the following cases:
   191  //
   192  //     * int != 0
   193  //     * uint != 0
   194  //     * float != 0.0
   195  //     * len(array/chan/map/slice/string) > 0
   196  //     * bool == true
   197  //     * underlying value is a struct
   198  //
   199  // Otherwise returns always FALSE.
   200  func (v *Value) IsTrue() bool {
   201  	switch v.getResolvedValue().Kind() {
   202  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   203  		return v.getResolvedValue().Int() != 0
   204  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   205  		return v.getResolvedValue().Uint() != 0
   206  	case reflect.Float32, reflect.Float64:
   207  		return v.getResolvedValue().Float() != 0
   208  	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
   209  		return v.getResolvedValue().Len() > 0
   210  	case reflect.Bool:
   211  		return v.getResolvedValue().Bool()
   212  	case reflect.Struct:
   213  		return true // struct instance is always true
   214  	default:
   215  		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
   216  		return false
   217  	}
   218  }
   219  
   220  // Tries to negate the underlying value. It's mainly used for
   221  // the NOT-operator and in conjunction with a call to
   222  // return_value.IsTrue() afterwards.
   223  //
   224  // Example:
   225  //     AsValue(1).Negate().IsTrue() == false
   226  func (v *Value) Negate() *Value {
   227  	switch v.getResolvedValue().Kind() {
   228  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   229  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   230  		if v.Integer() != 0 {
   231  			return AsValue(0)
   232  		} else {
   233  			return AsValue(1)
   234  		}
   235  	case reflect.Float32, reflect.Float64:
   236  		if v.Float() != 0.0 {
   237  			return AsValue(float64(0.0))
   238  		} else {
   239  			return AsValue(float64(1.1))
   240  		}
   241  	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
   242  		return AsValue(v.getResolvedValue().Len() == 0)
   243  	case reflect.Bool:
   244  		return AsValue(!v.getResolvedValue().Bool())
   245  	default:
   246  		logf("Value.IsTrue() not available for type: %s\n", v.getResolvedValue().Kind().String())
   247  		return AsValue(true)
   248  	}
   249  }
   250  
   251  // Returns the length for an array, chan, map, slice or string.
   252  // Otherwise it will return 0.
   253  func (v *Value) Len() int {
   254  	switch v.getResolvedValue().Kind() {
   255  	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
   256  		return v.getResolvedValue().Len()
   257  	case reflect.String:
   258  		runes := []rune(v.getResolvedValue().String())
   259  		return len(runes)
   260  	default:
   261  		logf("Value.Len() not available for type: %s\n", v.getResolvedValue().Kind().String())
   262  		return 0
   263  	}
   264  }
   265  
   266  // Slices an array, slice or string. Otherwise it will
   267  // return an empty []int.
   268  func (v *Value) Slice(i, j int) *Value {
   269  	switch v.getResolvedValue().Kind() {
   270  	case reflect.Array, reflect.Slice:
   271  		return AsValue(v.getResolvedValue().Slice(i, j).Interface())
   272  	case reflect.String:
   273  		runes := []rune(v.getResolvedValue().String())
   274  		return AsValue(string(runes[i:j]))
   275  	default:
   276  		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
   277  		return AsValue([]int{})
   278  	}
   279  }
   280  
   281  // Get the i-th item of an array, slice or string. Otherwise
   282  // it will return NIL.
   283  func (v *Value) Index(i int) *Value {
   284  	switch v.getResolvedValue().Kind() {
   285  	case reflect.Array, reflect.Slice:
   286  		if i >= v.Len() {
   287  			return AsValue(nil)
   288  		}
   289  		return AsValue(v.getResolvedValue().Index(i).Interface())
   290  	case reflect.String:
   291  		//return AsValue(v.getResolvedValue().Slice(i, i+1).Interface())
   292  		s := v.getResolvedValue().String()
   293  		runes := []rune(s)
   294  		if i < len(runes) {
   295  			return AsValue(string(runes[i]))
   296  		}
   297  		return AsValue("")
   298  	default:
   299  		logf("Value.Slice() not available for type: %s\n", v.getResolvedValue().Kind().String())
   300  		return AsValue([]int{})
   301  	}
   302  }
   303  
   304  // Checks whether the underlying value (which must be of type struct, map,
   305  // string, array or slice) contains of another Value (e. g. used to check
   306  // whether a struct contains of a specific field or a map contains a specific key).
   307  //
   308  // Example:
   309  //     AsValue("Hello, World!").Contains(AsValue("World")) == true
   310  func (v *Value) Contains(other *Value) bool {
   311  	switch v.getResolvedValue().Kind() {
   312  	case reflect.Struct:
   313  		field_value := v.getResolvedValue().FieldByName(other.String())
   314  		return field_value.IsValid()
   315  	case reflect.Map:
   316  		var map_value reflect.Value
   317  		switch other.Interface().(type) {
   318  		case int:
   319  			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
   320  		case string:
   321  			map_value = v.getResolvedValue().MapIndex(other.getResolvedValue())
   322  		default:
   323  			logf("Value.Contains() does not support lookup type '%s'\n", other.getResolvedValue().Kind().String())
   324  			return false
   325  		}
   326  
   327  		return map_value.IsValid()
   328  	case reflect.String:
   329  		return strings.Contains(v.getResolvedValue().String(), other.String())
   330  
   331  	// TODO: reflect.Array, reflect.Slice
   332  
   333  	default:
   334  		logf("Value.Contains() not available for type: %s\n", v.getResolvedValue().Kind().String())
   335  		return false
   336  	}
   337  }
   338  
   339  // Checks whether the underlying value is of type array, slice or string.
   340  // You normally would use CanSlice() before using the Slice() operation.
   341  func (v *Value) CanSlice() bool {
   342  	switch v.getResolvedValue().Kind() {
   343  	case reflect.Array, reflect.Slice, reflect.String:
   344  		return true
   345  	}
   346  	return false
   347  }
   348  
   349  // Iterates over a map, array, slice or a string. It calls the
   350  // function's first argument for every value with the following arguments:
   351  //
   352  //     idx      current 0-index
   353  //     count    total amount of items
   354  //     key      *Value for the key or item
   355  //     value    *Value (only for maps, the respective value for a specific key)
   356  //
   357  // If the underlying value has no items or is not one of the types above,
   358  // the empty function (function's second argument) will be called.
   359  func (v *Value) Iterate(fn func(idx, count int, key, value *Value) bool, empty func()) {
   360  	v.IterateOrder(fn, empty, false)
   361  }
   362  
   363  // Like Value.Iterate, but can iterate through an array/slice/string in reverse. Does
   364  // not affect the iteration through a map because maps don't have any particular order.
   365  func (v *Value) IterateOrder(fn func(idx, count int, key, value *Value) bool, empty func(), reverse bool) {
   366  	switch v.getResolvedValue().Kind() {
   367  	case reflect.Map:
   368  		// Reverse not needed for maps, since they are not ordered
   369  		keys := v.getResolvedValue().MapKeys()
   370  		keyLen := len(keys)
   371  		for idx, key := range keys {
   372  			value := v.getResolvedValue().MapIndex(key)
   373  			if !fn(idx, keyLen, &Value{val: key}, &Value{val: value}) {
   374  				return
   375  			}
   376  		}
   377  		if keyLen == 0 {
   378  			empty()
   379  		}
   380  		return // done
   381  	case reflect.Array, reflect.Slice:
   382  		itemCount := v.getResolvedValue().Len()
   383  		if itemCount > 0 {
   384  			if reverse {
   385  				for i := itemCount - 1; i >= 0; i-- {
   386  					if !fn(i, itemCount, &Value{val: v.getResolvedValue().Index(i)}, nil) {
   387  						return
   388  					}
   389  				}
   390  			} else {
   391  				for i := 0; i < itemCount; i++ {
   392  					if !fn(i, itemCount, &Value{val: v.getResolvedValue().Index(i)}, nil) {
   393  						return
   394  					}
   395  				}
   396  			}
   397  		} else {
   398  			empty()
   399  		}
   400  		return // done
   401  	case reflect.String:
   402  		// TODO: Not utf8-compatible (utf8-decoding neccessary)
   403  		charCount := v.getResolvedValue().Len()
   404  		if charCount > 0 {
   405  			if reverse {
   406  				for i := charCount - 1; i >= 0; i-- {
   407  					if !fn(i, charCount, &Value{val: v.getResolvedValue().Slice(i, i+1)}, nil) {
   408  						return
   409  					}
   410  				}
   411  			} else {
   412  				for i := 0; i < charCount; i++ {
   413  					if !fn(i, charCount, &Value{val: v.getResolvedValue().Slice(i, i+1)}, nil) {
   414  						return
   415  					}
   416  				}
   417  			}
   418  		} else {
   419  			empty()
   420  		}
   421  		return // done
   422  	default:
   423  		logf("Value.Iterate() not available for type: %s\n", v.getResolvedValue().Kind().String())
   424  	}
   425  	empty()
   426  }
   427  
   428  // Gives you access to the underlying value.
   429  func (v *Value) Interface() interface{} {
   430  	if v.val.IsValid() {
   431  		return v.val.Interface()
   432  	}
   433  	return nil
   434  }
   435  
   436  // Checks whether two values are containing the same value or object.
   437  func (v *Value) EqualValueTo(other *Value) bool {
   438  	return v.Interface() == other.Interface()
   439  }