github.com/codingeasygo/util@v0.0.0-20231206062002-1ce2f004b7d9/xmap/map.go (about) 1 package xmap 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "reflect" 8 "strconv" 9 "strings" 10 "sync" 11 12 "github.com/codingeasygo/util/attrvalid" 13 14 "github.com/codingeasygo/util/converter" 15 ) 16 17 // BaseValuable is interface which can be store value 18 type BaseValuable interface { 19 ValueVal(path ...string) (v interface{}, err error) 20 //SetValue will set value to path 21 SetValue(path string, val interface{}) (err error) 22 //Delete will delete value on path 23 Delete(path string) (err error) 24 //Clear will clear all key on map 25 Clear() (err error) 26 //Length will return value count 27 Length() (l int) 28 //Exist will return true if key having 29 Exist(path ...string) bool 30 } 31 32 // RawMapable will get the raw map 33 type RawMapable interface { 34 RawMap() map[string]interface{} 35 } 36 37 // Valuable is interface which can be store and convert value 38 type Valuable interface { 39 attrvalid.ValueGetter 40 attrvalid.Validable 41 BaseValuable 42 //Raw will return raw base valuable 43 Raw() BaseValuable 44 //Int will convert path value to int 45 Int(path ...string) int 46 //IntDef will convert path value to int, return default when not exist or convert fail 47 IntDef(def int, path ...string) (v int) 48 //IntVal will convert path value to int, return error when not exist or convert fail 49 IntVal(path ...string) (int, error) 50 //Int64 will convert path value to int64 51 Int64(path ...string) int64 52 //Int64Def will convert path value to int64, return default when not exist or convert fail 53 Int64Def(def int64, path ...string) (v int64) 54 //Int64Val will convert path value to int64, return error when not exist or convert fail 55 Int64Val(path ...string) (int64, error) 56 //Uint64 will convert path value to uint64 57 Uint64(path ...string) uint64 58 //Uint64Def will convert path value to uint64, return default when not exist or convert fail 59 Uint64Def(def uint64, path ...string) (v uint64) 60 //Uint64Val will convert path value to uint64, return error when not exist or convert fail 61 Uint64Val(path ...string) (uint64, error) 62 //Float64 will convert path value to float64 63 Float64(path ...string) float64 64 //Float64Def will convert path value to float64, return default when not exist or convert fail 65 Float64Def(def float64, path ...string) (v float64) 66 //Float64Val will convert path value to float64, return error when not exist or convert fail 67 Float64Val(path ...string) (float64, error) 68 //Str will convert path value to string 69 Str(path ...string) string 70 //StrDef will convert path value to string, return default when not exist or convert fail 71 StrDef(def string, path ...string) (v string) 72 //StrVal will convert path value to string, return error when not exist or convert fail 73 StrVal(path ...string) (string, error) 74 //Map will convert path value to map 75 Map(path ...string) M 76 //MapDef will convert path value to map, return default when not exist or convert fail 77 MapDef(def M, path ...string) (v M) 78 //MapVal will convert path value to map, return error when not exist or convert fail 79 MapVal(path ...string) (M, error) 80 //ArrayDef will convert path value to array, return default when not exist or convert fail 81 ArrayDef(def []interface{}, path ...string) []interface{} 82 //ArrayVal will convert path value to interface{} array, return error when not exist or convert fail 83 ArrayVal(path ...string) ([]interface{}, error) 84 //ArrayMapDef will convert path value to map array, return default when not exist or convert fail 85 ArrayMapDef(def []M, path ...string) []M 86 //ArrayMapVal will convert path value to map array, return error when not exist or convert fail 87 ArrayMapVal(path ...string) ([]M, error) 88 //ArrayStrDef will convert path value to string array, return default when not exist or convert fail 89 ArrayStrDef(def []string, path ...string) []string 90 //ArrayStrVal will convert path value to string array, return error when not exist or convert fail 91 ArrayStrVal(path ...string) ([]string, error) 92 //ArrayIntDef will convert path value to int array, return default when not exist or convert fail 93 ArrayIntDef(def []int, path ...string) []int 94 //ArrayIntVal will convert path value to int array, return error when not exist or convert fail 95 ArrayIntVal(path ...string) ([]int, error) 96 //ArrayInt64Def will convert path value to int64 array, return default when not exist or convert fail 97 ArrayInt64Def(def []int64, path ...string) []int64 98 //ArrayInt64Val will convert path value to int64 array, return error when not exist or convert fail 99 ArrayInt64Val(path ...string) ([]int64, error) 100 //ArrayUint64Def will convert path value to uint64 array, return default when not exist or convert fail 101 ArrayUint64Def(def []uint64, path ...string) []uint64 102 //ArrayUint64Val will convert path value to uint64 array, return error when not exist or convert fail 103 ArrayUint64Val(path ...string) ([]uint64, error) 104 //ArrayFloat64Def will convert path value to float64 array, return default when not exist or convert fail 105 ArrayFloat64Def(def []float64, path ...string) []float64 106 //ArrayFloat64Val will convert path value to float64 array, return error when not exist or convert fail 107 ArrayFloat64Val(path ...string) ([]float64, error) 108 //Value will convert path value to interface{} 109 Value(path ...string) interface{} 110 //ReplaceAll will replace all value by ${path} 111 ReplaceAll(in string, usingEnv, keepEmpty bool) (out string) 112 } 113 114 type impl struct { 115 BaseValuable 116 } 117 118 // Raw will return raw base valuable 119 func (i *impl) Raw() BaseValuable { 120 return i.BaseValuable 121 } 122 123 // Int will convert path value to int 124 func (i *impl) Int(path ...string) int { 125 return converter.Int(i.Value(path...)) 126 } 127 128 // IntDef will convert path value to int, return default when not exist or convert fail 129 func (i *impl) IntDef(def int, path ...string) (v int) { 130 v, err := i.IntVal(path...) 131 if err != nil { 132 v = def 133 } 134 return 135 } 136 137 // IntVal will convert path value to int, return error when not exist or convert fail 138 func (i *impl) IntVal(path ...string) (int, error) { 139 return converter.IntVal(i.Value(path...)) 140 } 141 142 // Int64 will convert path value to int64 143 func (i *impl) Int64(path ...string) int64 { 144 return converter.Int64(i.Value(path...)) 145 } 146 147 // Int64Def will convert path value to int64, return default when not exist or convert fail 148 func (i *impl) Int64Def(def int64, path ...string) (v int64) { 149 v, err := i.Int64Val(path...) 150 if err != nil { 151 v = def 152 } 153 return 154 } 155 156 // Int64Val will convert path value to int64, return error when not exist or convert fail 157 func (i *impl) Int64Val(path ...string) (int64, error) { 158 return converter.Int64Val(i.Value(path...)) 159 } 160 161 // Uint64 will convert path value to uint64 162 func (i *impl) Uint64(path ...string) uint64 { 163 return converter.Uint64(i.Value(path...)) 164 } 165 166 // Uint64Def will convert path value to uint64, return default when not exist or convert fail 167 func (i *impl) Uint64Def(def uint64, path ...string) (v uint64) { 168 v, err := i.Uint64Val(path...) 169 if err != nil { 170 v = def 171 } 172 return 173 } 174 175 // Uint64Val will convert path value to uint64, return error when not exist or convert fail 176 func (i *impl) Uint64Val(path ...string) (uint64, error) { 177 return converter.Uint64Val(i.Value(path...)) 178 } 179 180 // Float64 will convert path value to float64 181 func (i *impl) Float64(path ...string) float64 { 182 return converter.Float64(i.Value(path...)) 183 } 184 185 // Float64Def will convert path value to float64, return default when not exist or convert fail 186 func (i *impl) Float64Def(def float64, path ...string) (v float64) { 187 v, err := i.Float64Val(path...) 188 if err != nil { 189 v = def 190 } 191 return 192 } 193 194 // Float64Val will convert path value to float64, return error when not exist or convert fail 195 func (i *impl) Float64Val(path ...string) (float64, error) { 196 return converter.Float64Val(i.Value(path...)) 197 } 198 199 // Str will convert path value to string 200 func (i *impl) Str(path ...string) string { 201 return converter.String(i.Value(path...)) 202 } 203 204 // StrDef will convert path value to string, return default when not exist or convert fail 205 func (i *impl) StrDef(def string, path ...string) (v string) { 206 v, err := i.StrVal(path...) 207 if err != nil { 208 v = def 209 } 210 return 211 } 212 213 // StrVal will convert path value to string, return error when not exist or convert fail 214 func (i *impl) StrVal(path ...string) (string, error) { 215 return converter.StringVal(i.Value(path...)) 216 } 217 218 // Map will convert path value to map 219 func (i *impl) Map(path ...string) M { 220 v, _ := MapVal(i.Value(path...)) 221 return v 222 } 223 224 // MapDef will convert path value to map, return default when not exist or convert fail 225 func (i *impl) MapDef(def M, path ...string) (v M) { 226 v, err := i.MapVal(path...) 227 if err != nil { 228 v = def 229 } 230 return 231 } 232 233 // MapVal will convert path value to map, return error when not exist or convert fail 234 func (i *impl) MapVal(path ...string) (M, error) { 235 return MapVal(i.Value(path...)) 236 } 237 238 // ArrayDef will convert path value to interface{} array, return default when not exist or convert fail 239 func (i *impl) ArrayDef(def []interface{}, path ...string) []interface{} { 240 vals, err := i.ArrayVal(path...) 241 if err != nil { 242 vals = def 243 } 244 return vals 245 } 246 247 // ArrayVal will convert path value to interface{} array, return error when not exist or convert fail 248 func (i *impl) ArrayVal(path ...string) ([]interface{}, error) { 249 return converter.ArrayVal(i.Value(path...)) 250 } 251 252 // ArrayMapDef will convert path value to interface{} array, return default when not exist or convert fail 253 func (i *impl) ArrayMapDef(def []M, path ...string) []M { 254 vals, err := i.ArrayMapVal(path...) 255 if err != nil || len(vals) < 1 { 256 vals = def 257 } 258 return vals 259 } 260 261 // ArrayMapVal will convert path value to map array, return error when not exist or convert fail 262 func (i *impl) ArrayMapVal(path ...string) ([]M, error) { 263 return ArrayMapVal(i.Value(path...)) 264 } 265 266 // ArrayStrDef will convert path value to string array, return default when not exist or convert fail 267 func (i *impl) ArrayStrDef(def []string, path ...string) []string { 268 vals, err := i.ArrayStrVal(path...) 269 if err != nil { 270 vals = def 271 } 272 return vals 273 } 274 275 // ArrayStrVal will convert path value to string array, return error when not exist or convert fail 276 func (i *impl) ArrayStrVal(path ...string) ([]string, error) { 277 return converter.ArrayStringVal(i.Value(path...)) 278 } 279 280 // ArrayIntDef will convert path value to string array, return default when not exist or convert fail 281 func (i *impl) ArrayIntDef(def []int, path ...string) []int { 282 vals, err := i.ArrayIntVal(path...) 283 if err != nil { 284 vals = def 285 } 286 return vals 287 } 288 289 // ArrayIntVal will convert path value to int array, return error when not exist or convert fail 290 func (i *impl) ArrayIntVal(path ...string) ([]int, error) { 291 return converter.ArrayIntVal(i.Value(path...)) 292 } 293 294 // ArrayInt64Def will convert path value to int64 array, return default when not exist or convert fail 295 func (i *impl) ArrayInt64Def(def []int64, path ...string) []int64 { 296 vals, err := i.ArrayInt64Val(path...) 297 if err != nil { 298 vals = def 299 } 300 return vals 301 } 302 303 // ArrayInt64Val will convert path value to int64 array, return error when not exist or convert fail 304 func (i *impl) ArrayInt64Val(path ...string) ([]int64, error) { 305 return converter.ArrayInt64Val(i.Value(path...)) 306 } 307 308 // ArrayUint64Def will convert path value to uint64 array, return default when not exist or convert fail 309 func (i *impl) ArrayUint64Def(def []uint64, path ...string) []uint64 { 310 vals, err := i.ArrayUint64Val(path...) 311 if err != nil { 312 vals = def 313 } 314 return vals 315 } 316 317 // ArrayUint64Val will convert path value to uint64 array, return error when not exist or convert fail 318 func (i *impl) ArrayUint64Val(path ...string) ([]uint64, error) { 319 return converter.ArrayUint64Val(i.Value(path...)) 320 } 321 322 // ArrayFloat64Def will convert path value to float64 array, return default when not exist or convert fail 323 func (i *impl) ArrayFloat64Def(def []float64, path ...string) []float64 { 324 vals, err := i.ArrayFloat64Val(path...) 325 if err != nil { 326 vals = def 327 } 328 return vals 329 } 330 331 // ArrayFloat64Val will convert path value to float64 array, return error when not exist or convert fail 332 func (i *impl) ArrayFloat64Val(path ...string) ([]float64, error) { 333 return converter.ArrayFloat64Val(i.Value(path...)) 334 } 335 336 // Value will convert path value to interface{} 337 func (i *impl) Value(path ...string) interface{} { 338 v, _ := i.ValueVal(path...) 339 return v 340 } 341 342 // Get is implement for attrvalid.ValueGetter 343 func (i *impl) Get(path string) (interface{}, error) { 344 return i.Value(strings.Split(path, "|")...), nil 345 } 346 347 // ValidFormat is implement for attrvalid.Validable 348 func (i *impl) ValidFormat(f string, args ...interface{}) error { 349 return attrvalid.ValidAttrFormat(f, i, true, args...) 350 } 351 352 // ReplaceAll will replace value by ${xx}, which xx is having 353 func (i *impl) ReplaceAll(in string, usingEnv, keepEmpty bool) (out string) { 354 out = ReplaceAll(func(key string) interface{} { 355 v, err := i.ValueVal(key) 356 if err != nil { 357 return nil 358 } 359 return v 360 }, in, usingEnv, keepEmpty) 361 return 362 } 363 364 // MapVal will conventer value to map 365 func MapVal(v interface{}) (M, error) { 366 if mv, ok := v.(M); ok { 367 return mv, nil 368 } else if mv, ok := v.(map[string]interface{}); ok { 369 return M(mv), nil 370 } else if rm, ok := v.(RawMapable); ok { 371 mv = M(rm.RawMap()) 372 return mv, nil 373 } else if sv, ok := v.(string); ok { 374 mv := M{} 375 return mv, json.Unmarshal([]byte(sv), &mv) 376 } else if sv, ok := v.([]byte); ok { 377 mv := M{} 378 return mv, json.Unmarshal(sv, &mv) 379 } else { 380 return nil, fmt.Errorf("incompactable kind(%v)", reflect.ValueOf(v).Kind()) 381 } 382 } 383 384 // ArrayMapVal will convert value to map array 385 func ArrayMapVal(v interface{}) (mvals []M, err error) { 386 if v == nil { 387 return nil, nil 388 } 389 var mval M 390 if vals, ok := v.([]M); ok { 391 return vals, nil 392 } else if vals, ok := v.([]interface{}); ok { 393 for _, v := range vals { 394 mval, err = MapVal(v) 395 if err != nil { 396 return 397 } 398 mvals = append(mvals, mval) 399 } 400 return 401 } else if vals, ok := v.([]map[string]interface{}); ok { 402 for _, v := range vals { 403 mvals = append(mvals, M(v)) 404 } 405 } 406 if sv, ok := v.(string); ok { 407 err = json.Unmarshal([]byte(sv), &mvals) 408 return 409 } 410 if sv, ok := v.([]byte); ok { 411 err = json.Unmarshal(sv, &mvals) 412 return 413 } 414 vals := reflect.ValueOf(v) 415 if vals.Kind() != reflect.Slice { 416 err = fmt.Errorf("incompactable kind(%v)", vals.Kind()) 417 return 418 } 419 for i := 0; i < vals.Len(); i++ { 420 if vals.Index(i).IsZero() { 421 mval, err = MapVal(nil) 422 } else { 423 mval, err = MapVal(vals.Index(i).Interface()) 424 } 425 if err != nil { 426 return 427 } 428 mvals = append(mvals, mval) 429 } 430 return 431 } 432 433 // M is type define to map[string]interface{} 434 type M map[string]interface{} 435 436 // New will create map Valuable 437 func New() (m M) { 438 return M{} 439 } 440 441 // ValueVal will convert path value to value, return error when not exist or convert fail 442 func (m M) ValueVal(path ...string) (v interface{}, err error) { 443 for _, p := range path { 444 v, err = m.pathValue(p) 445 if err == nil { 446 break 447 } 448 } 449 return 450 } 451 452 // SetValue will set value to path 453 func (m M) SetValue(path string, val interface{}) (err error) { 454 if len(path) < 1 { 455 err = fmt.Errorf("path is empty") 456 return 457 } 458 path = strings.TrimPrefix(path, "/") 459 keys := strings.Split(path, "/") 460 if len(keys) == 1 { 461 m.setValue(keys[0], val) 462 } else { 463 err = m.setPathValue(path, val) 464 } 465 return 466 } 467 468 // Delete will delete value on path 469 func (m M) Delete(path string) (err error) { 470 return m.setPathValue(path, nil) 471 } 472 473 // Clear will clear all key on map 474 func (m M) Clear() (err error) { 475 for key := range m { 476 delete(m, key) 477 } 478 return 479 } 480 481 func (m M) setValue(path string, val interface{}) { 482 if val == nil { 483 delete(m, path) 484 } else { 485 m[path] = val 486 } 487 } 488 489 func (m M) pathValue(path string) (interface{}, error) { 490 if v, ok := m[path]; ok { 491 return v, nil 492 } 493 path = strings.TrimPrefix(path, "/") 494 keys := []string{} 495 key := strings.Builder{} 496 wrapped := false 497 for _, c := range path { 498 switch c { 499 case '\\': 500 wrapped = true 501 case '/': 502 if wrapped { 503 key.WriteRune(c) 504 wrapped = false 505 } else { 506 keys = append(keys, key.String()) 507 key = strings.Builder{} 508 } 509 default: 510 key.WriteRune(c) 511 } 512 } 513 if key.Len() > 0 { 514 keys = append(keys, key.String()) 515 key = strings.Builder{} 516 } 517 return m.valP(keys...) 518 } 519 520 func (m M) valP(keys ...string) (interface{}, error) { 521 count := len(keys) 522 var tv interface{} = m 523 for i := 0; i < count; i++ { 524 if tv == nil { 525 break 526 } 527 switch reflect.TypeOf(tv).Kind() { 528 case reflect.Slice: //if array 529 ary, ok := tv.([]interface{}) //check if valid array 530 if !ok { 531 return nil, fmt.Errorf( 532 "invalid array(%v) in path(/%v),expected []interface{}", 533 reflect.TypeOf(tv).String(), strings.Join(keys[:i+1], "/"), 534 ) 535 } 536 if keys[i] == "@len" { //check if have @len 537 return len(ary), nil //return the array length 538 } 539 idx, err := strconv.Atoi(keys[i]) //get the target index. 540 if err != nil { 541 return nil, fmt.Errorf( 542 "invalid array index(/%v)", strings.Join(keys[:i+1], "/"), 543 ) 544 } 545 if idx >= len(ary) || idx < 0 { //check index valid 546 return nil, fmt.Errorf( 547 "array out of index in path(/%v)", strings.Join(keys[:i+1], "/"), 548 ) 549 } 550 tv = ary[idx] 551 continue 552 case reflect.Map: //if map 553 tm, _ := MapVal(tv) //check map covert 554 if tm == nil { 555 return nil, fmt.Errorf( 556 "invalid map in path(/%v)", strings.Join(keys[:i], "/"), 557 ) 558 } 559 tv = tm[keys[i]] 560 continue 561 default: //unknow type 562 return nil, fmt.Errorf( 563 "invalid type(%v) in path(/%v)", 564 reflect.TypeOf(tv).Kind(), strings.Join(keys[:i], "/"), 565 ) 566 } 567 } 568 if tv == nil { //if valud not found 569 return nil, fmt.Errorf( 570 "value not found in path(/%v)", strings.Join(keys, "/"), 571 ) 572 } 573 return tv, nil 574 } 575 576 func (m M) setPathValue(path string, val interface{}) error { 577 if len(path) < 1 { 578 return errors.New("path is empty") 579 } 580 path = strings.TrimPrefix(path, "/") 581 keys := strings.Split(path, "/") 582 // 583 i := len(keys) - 1 584 pv, err := m.valP(keys[:i]...) 585 if err != nil { 586 return err 587 } 588 switch reflect.TypeOf(pv).Kind() { 589 case reflect.Slice: 590 ary, ok := pv.([]interface{}) //check if valid array 591 if !ok { 592 return fmt.Errorf( 593 "invalid array(%v) in path(/%v),expected []interface{}", 594 reflect.TypeOf(pv).String(), strings.Join(keys[:i+1], "/"), 595 ) 596 } 597 idx, err := strconv.Atoi(keys[i]) //get the target index. 598 if err != nil { 599 return fmt.Errorf( 600 "invalid array index(/%v)", strings.Join(keys[:i+1], "/"), 601 ) 602 } 603 if idx >= len(ary) || idx < 0 { //check index valid 604 return fmt.Errorf( 605 "array out of index in path(/%v)", strings.Join(keys[:i+1], "/"), 606 ) 607 } 608 ary[idx] = val 609 case reflect.Map: 610 tm, _ := MapVal(pv) //check map covert 611 if tm == nil { 612 return fmt.Errorf( 613 "invalid map in path(/%v)", strings.Join(keys[:i], "/"), 614 ) 615 } 616 tm.setValue(keys[i], val) 617 default: //unknow type 618 return fmt.Errorf( 619 "not map type(%v) in path(/%v)", 620 reflect.TypeOf(pv).Kind(), strings.Join(keys[:i], "/"), 621 ) 622 } 623 return nil 624 } 625 626 // Length will return value count 627 func (m M) Length() (l int) { 628 l = len(m) 629 return 630 } 631 632 // Exist will return true if key having 633 func (m M) Exist(path ...string) bool { 634 _, err := m.ValueVal(path...) 635 return err == nil 636 } 637 638 // Raw will return raw base valuable 639 func (m M) Raw() BaseValuable { 640 return m 641 } 642 643 // Int will convert path value to int 644 func (m M) Int(path ...string) int { 645 return converter.Int(m.Value(path...)) 646 } 647 648 // IntDef will convert path value to int, return default when not exist or convert fail 649 func (m M) IntDef(def int, path ...string) (v int) { 650 v, err := m.IntVal(path...) 651 if err != nil { 652 v = def 653 } 654 return 655 } 656 657 // IntVal will convert path value to int, return error when not exist or convert fail 658 func (m M) IntVal(path ...string) (int, error) { 659 return converter.IntVal(m.Value(path...)) 660 } 661 662 // Int64 will convert path value to int64 663 func (m M) Int64(path ...string) int64 { 664 return converter.Int64(m.Value(path...)) 665 } 666 667 // Int64Def will convert path value to int64, return default when not exist or convert fail 668 func (m M) Int64Def(def int64, path ...string) (v int64) { 669 v, err := m.Int64Val(path...) 670 if err != nil { 671 v = def 672 } 673 return 674 } 675 676 // Int64Val will convert path value to int64, return error when not exist or convert fail 677 func (m M) Int64Val(path ...string) (int64, error) { 678 return converter.Int64Val(m.Value(path...)) 679 } 680 681 // Uint64 will convert path value to uint64 682 func (m M) Uint64(path ...string) uint64 { 683 return converter.Uint64(m.Value(path...)) 684 } 685 686 // Uint64Def will convert path value to uint64, return default when not exist or convert fail 687 func (m M) Uint64Def(def uint64, path ...string) (v uint64) { 688 v, err := m.Uint64Val(path...) 689 if err != nil { 690 v = def 691 } 692 return 693 } 694 695 // Uint64Val will convert path value to uint64, return error when not exist or convert fail 696 func (m M) Uint64Val(path ...string) (uint64, error) { 697 return converter.Uint64Val(m.Value(path...)) 698 } 699 700 // Float64 will convert path value to float64 701 func (m M) Float64(path ...string) float64 { 702 return converter.Float64(m.Value(path...)) 703 } 704 705 // Float64Def will convert path value to float64, return default when not exist or convert fail 706 func (m M) Float64Def(def float64, path ...string) (v float64) { 707 v, err := m.Float64Val(path...) 708 if err != nil { 709 v = def 710 } 711 return 712 } 713 714 // Float64Val will convert path value to float64, return error when not exist or convert fail 715 func (m M) Float64Val(path ...string) (float64, error) { 716 return converter.Float64Val(m.Value(path...)) 717 } 718 719 // Str will convert path value to string 720 func (m M) Str(path ...string) string { 721 return converter.String(m.Value(path...)) 722 } 723 724 // StrDef will convert path value to string, return default when not exist or convert fail 725 func (m M) StrDef(def string, path ...string) (v string) { 726 v, err := m.StrVal(path...) 727 if err != nil { 728 v = def 729 } 730 return 731 } 732 733 // StrVal will convert path value to string, return error when not exist or convert fail 734 func (m M) StrVal(path ...string) (string, error) { 735 return converter.StringVal(m.Value(path...)) 736 } 737 738 // Map will convert path value to map 739 func (m M) Map(path ...string) M { 740 v, _ := MapVal(m.Value(path...)) 741 return v 742 } 743 744 // MapDef will convert path value to map, return default when not exist or convert fail 745 func (m M) MapDef(def M, path ...string) (v M) { 746 v, err := m.MapVal(path...) 747 if err != nil { 748 v = def 749 } 750 return 751 } 752 753 // MapVal will convert path value to map, return error when not exist or convert fail 754 func (m M) MapVal(path ...string) (M, error) { 755 return MapVal(m.Value(path...)) 756 } 757 758 // ArrayDef will convert path value to interface{} array, return default when not exist or convert fail 759 func (m M) ArrayDef(def []interface{}, path ...string) []interface{} { 760 vals, err := m.ArrayVal(path...) 761 if err != nil { 762 vals = def 763 } 764 return vals 765 } 766 767 // ArrayVal will convert path value to interface{} array, return error when not exist or convert fail 768 func (m M) ArrayVal(path ...string) ([]interface{}, error) { 769 return converter.ArrayVal(m.Value(path...)) 770 } 771 772 // ArrayMapDef will convert path value to interface{} array, return default when not exist or convert fail 773 func (m M) ArrayMapDef(def []M, path ...string) []M { 774 vals, err := m.ArrayMapVal(path...) 775 if err != nil || len(vals) < 1 { 776 vals = def 777 } 778 return vals 779 } 780 781 // ArrayMapVal will convert path value to map array, return error when not exist or convert fail 782 func (m M) ArrayMapVal(path ...string) ([]M, error) { 783 return ArrayMapVal(m.Value(path...)) 784 } 785 786 // ArrayStrDef will convert path value to string array, return default when not exist or convert fail 787 func (m M) ArrayStrDef(def []string, path ...string) []string { 788 vals, err := m.ArrayStrVal(path...) 789 if err != nil { 790 vals = def 791 } 792 return vals 793 } 794 795 // ArrayStrVal will convert path value to string array, return error when not exist or convert fail 796 func (m M) ArrayStrVal(path ...string) ([]string, error) { 797 return converter.ArrayStringVal(m.Value(path...)) 798 } 799 800 // ArrayIntDef will convert path value to string array, return default when not exist or convert fail 801 func (m M) ArrayIntDef(def []int, path ...string) []int { 802 vals, err := m.ArrayIntVal(path...) 803 if err != nil { 804 vals = def 805 } 806 return vals 807 } 808 809 // ArrayIntVal will convert path value to int array, return error when not exist or convert fail 810 func (m M) ArrayIntVal(path ...string) ([]int, error) { 811 return converter.ArrayIntVal(m.Value(path...)) 812 } 813 814 // ArrayInt64Def will convert path value to int64 array, return default when not exist or convert fail 815 func (m M) ArrayInt64Def(def []int64, path ...string) []int64 { 816 vals, err := m.ArrayInt64Val(path...) 817 if err != nil { 818 vals = def 819 } 820 return vals 821 } 822 823 // ArrayInt64Val will convert path value to int64 array, return error when not exist or convert fail 824 func (m M) ArrayInt64Val(path ...string) ([]int64, error) { 825 return converter.ArrayInt64Val(m.Value(path...)) 826 } 827 828 // ArrayUint64Def will convert path value to uint64 array, return default when not exist or convert fail 829 func (m M) ArrayUint64Def(def []uint64, path ...string) []uint64 { 830 vals, err := m.ArrayUint64Val(path...) 831 if err != nil { 832 vals = def 833 } 834 return vals 835 } 836 837 // ArrayUint64Val will convert path value to uint64 array, return error when not exist or convert fail 838 func (m M) ArrayUint64Val(path ...string) ([]uint64, error) { 839 return converter.ArrayUint64Val(m.Value(path...)) 840 } 841 842 // ArrayFloat64Def will convert path value to float64 array, return default when not exist or convert fail 843 func (m M) ArrayFloat64Def(def []float64, path ...string) []float64 { 844 vals, err := m.ArrayFloat64Val(path...) 845 if err != nil { 846 vals = def 847 } 848 return vals 849 } 850 851 // ArrayFloat64Val will convert path value to float64 array, return error when not exist or convert fail 852 func (m M) ArrayFloat64Val(path ...string) ([]float64, error) { 853 return converter.ArrayFloat64Val(m.Value(path...)) 854 } 855 856 // Value will convert path value to interface{} 857 func (m M) Value(path ...string) interface{} { 858 v, _ := m.ValueVal(path...) 859 return v 860 } 861 862 // Get is implement for attrvalid.ValueGetter 863 func (m M) Get(path string) (interface{}, error) { 864 return m.Value(strings.Split(path, "|")...), nil 865 } 866 867 // ValidFormat is implement for attrvalid.Validable 868 func (m M) ValidFormat(f string, args ...interface{}) error { 869 return attrvalid.ValidAttrFormat(f, m, true, args...) 870 } 871 872 // ReplaceAll will replace input string by ${xx}, which xx is in values, 873 // if usingEnv is true, xx will check use env when vals is not having xx, 874 // if usingEmpty is true, xx will check use empty string when vals is not having xx and env is not exist 875 func (m M) ReplaceAll(in string, usingEnv, usingEmpty bool) (out string) { 876 out = ReplaceAll(func(key string) interface{} { 877 v, err := m.ValueVal(key) 878 if err != nil { 879 return nil 880 } 881 return v 882 }, in, usingEnv, usingEmpty) 883 return 884 } 885 886 func ValueEqual(a, b interface{}) bool { 887 if a == nil || b == nil { 888 return a == nil && b == nil 889 } 890 resultValue := reflect.ValueOf(a) 891 if !resultValue.CanConvert(reflect.TypeOf(b)) { 892 return false 893 } 894 targetValue := resultValue.Convert(reflect.TypeOf(b)).Interface() 895 return reflect.DeepEqual(targetValue, b) 896 } 897 898 func (m M) ValueEqual(key string, value interface{}) bool { 899 return ValueEqual(m.Value(key), value) 900 } 901 902 // SafeM is safe map 903 type SafeM struct { 904 Valuable 905 raw BaseValuable 906 locker sync.RWMutex 907 } 908 909 // NewSafe will return new safe map 910 func NewSafe() (m *SafeM) { 911 m = &SafeM{ 912 raw: M{}, 913 locker: sync.RWMutex{}, 914 } 915 m.Valuable = &impl{BaseValuable: m} 916 return 917 } 918 919 func NewSafeByBase(base BaseValuable) (m *SafeM) { 920 m = &SafeM{ 921 raw: base, 922 locker: sync.RWMutex{}, 923 } 924 m.Valuable = &impl{BaseValuable: m} 925 return 926 } 927 928 func (s *SafeM) Lock() { 929 s.locker.Lock() 930 } 931 932 func (s *SafeM) Unlock() { 933 s.locker.Unlock() 934 } 935 936 func (s *SafeM) RLock() { 937 s.locker.RLock() 938 } 939 940 func (s *SafeM) RUnlock() { 941 s.locker.RUnlock() 942 } 943 944 // Raw will return raw base 945 func (s *SafeM) Raw() BaseValuable { 946 return s.raw 947 } 948 949 // ValueVal will convert path value to value, return error when not exist or convert fail 950 func (s *SafeM) ValueVal(path ...string) (v interface{}, err error) { 951 s.locker.RLock() 952 defer s.locker.RUnlock() 953 return s.raw.ValueVal(path...) 954 } 955 956 // SetValue will set value to path 957 func (s *SafeM) SetValue(path string, val interface{}) (err error) { 958 s.locker.Lock() 959 defer s.locker.Unlock() 960 return s.raw.SetValue(path, val) 961 } 962 963 // Delete will delete value on path 964 func (s *SafeM) Delete(path string) (err error) { 965 s.locker.Lock() 966 defer s.locker.Unlock() 967 return s.raw.SetValue(path, nil) 968 } 969 970 // Clear will clear all key 971 func (s *SafeM) Clear() (err error) { 972 s.locker.Lock() 973 defer s.locker.Unlock() 974 return s.raw.Clear() 975 } 976 977 // Length will return value count 978 func (s *SafeM) Length() (l int) { 979 s.locker.RLock() 980 defer s.locker.RUnlock() 981 return s.raw.Length() 982 } 983 984 // Exist will return true if key having 985 func (s *SafeM) Exist(path ...string) bool { 986 s.locker.RLock() 987 defer s.locker.RUnlock() 988 return s.raw.Exist(path...) 989 } 990 991 // ReplaceAll will replace input string by ${xx}, which xx is in values, 992 // if usingEnv is true, xx will check use env when vals is not having xx, 993 // if usingEmpty is true, xx will check use empty string when vals is not having xx and env is not exist 994 func (s *SafeM) ReplaceAll(in string, usingEnv, usingEmpty bool) (out string) { 995 out = ReplaceAll(func(key string) interface{} { 996 v, err := s.ValueVal(key) 997 if err != nil { 998 return nil 999 } 1000 return v 1001 }, in, usingEnv, usingEmpty) 1002 return 1003 } 1004 1005 // func (m Map) ToS(dest interface{}) { 1006 // M2S(m, dest) 1007 // } 1008 1009 // func NewMap(f string) (Map, error) { 1010 // bys, err := ioutil.ReadFile(f) 1011 // if err != nil { 1012 // return nil, err 1013 // } 1014 // var kvs Map = Map{} 1015 // err = json.Unmarshal(bys, &kvs) 1016 // return kvs, err 1017 // } 1018 1019 // func NewMaps(f string) ([]Map, error) { 1020 // bys, err := ioutil.ReadFile(f) 1021 // if err != nil { 1022 // return nil, err 1023 // } 1024 // var kvs []Map = []Map{} 1025 // err = json.Unmarshal(bys, &kvs) 1026 // return kvs, err 1027 // } 1028 1029 type MSorter struct { 1030 All []M 1031 Path []string 1032 Type int //0 is int,1 is float,2 is string 1033 Desc bool 1034 } 1035 1036 func NewMSorter(all []M, vtype int, desc bool, path ...string) *MSorter { 1037 return &MSorter{ 1038 All: all, 1039 Path: path, 1040 Type: vtype, 1041 Desc: desc, 1042 } 1043 } 1044 func (m *MSorter) Len() int { 1045 return len(m.All) 1046 } 1047 1048 func (m *MSorter) Less(i, j int) bool { 1049 switch m.Type { 1050 case 0: 1051 if m.Desc { 1052 return m.All[i].Int(m.Path...) > m.All[j].Int(m.Path...) 1053 } 1054 return m.All[i].Int(m.Path...) < m.All[j].Int(m.Path...) 1055 case 1: 1056 if m.Desc { 1057 return m.All[i].Float64(m.Path...) > m.All[j].Float64(m.Path...) 1058 } 1059 return m.All[i].Float64(m.Path...) < m.All[j].Float64(m.Path...) 1060 default: 1061 if m.Desc { 1062 return m.All[i].Str(m.Path...) > m.All[j].Str(m.Path...) 1063 } 1064 return m.All[i].Str(m.Path...) < m.All[j].Str(m.Path...) 1065 } 1066 } 1067 func (m *MSorter) Swap(i, j int) { 1068 m.All[i], m.All[j] = m.All[j], m.All[i] 1069 } 1070 1071 type ValuableSorter struct { 1072 All []Valuable 1073 Path []string 1074 Type int //0 is int,1 is float,2 is string 1075 Desc bool 1076 } 1077 1078 func NewValuableSorter(all []Valuable, vtype int, desc bool, path ...string) *ValuableSorter { 1079 return &ValuableSorter{ 1080 All: all, 1081 Path: path, 1082 Type: vtype, 1083 Desc: desc, 1084 } 1085 } 1086 func (v *ValuableSorter) Len() int { 1087 return len(v.All) 1088 } 1089 1090 func (v *ValuableSorter) Less(i, j int) bool { 1091 switch v.Type { 1092 case 0: 1093 if v.Desc { 1094 return v.All[i].Int(v.Path...) > v.All[j].Int(v.Path...) 1095 } 1096 return v.All[i].Int(v.Path...) < v.All[j].Int(v.Path...) 1097 case 1: 1098 if v.Desc { 1099 return v.All[i].Float64(v.Path...) > v.All[j].Float64(v.Path...) 1100 } 1101 return v.All[i].Float64(v.Path...) < v.All[j].Float64(v.Path...) 1102 default: 1103 if v.Desc { 1104 return v.All[i].Str(v.Path...) > v.All[j].Str(v.Path...) 1105 } 1106 return v.All[i].Str(v.Path...) < v.All[j].Str(v.Path...) 1107 } 1108 } 1109 func (v *ValuableSorter) Swap(i, j int) { 1110 v.All[i], v.All[j] = v.All[j], v.All[i] 1111 } 1112 1113 // func Maps2Map(ms []Map, path ...string) Map { 1114 // var res = Map{} 1115 // for _, m := range ms { 1116 // res[m.StrValP(path)] = m 1117 // } 1118 // return res 1119 // }