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 }