github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/isc/string.go (about) 1 package isc 2 3 import ( 4 "fmt" 5 "github.com/dlclark/regexp2" 6 "regexp" 7 "strconv" 8 "strings" 9 ) 10 11 type ISCString string 12 13 func (s ISCString) At(index int) uint8 { 14 return s[index] 15 } 16 17 func (s ISCString) Length() int { 18 return len(s) 19 } 20 21 func (s ISCString) Chars() ISCList[uint8] { 22 var list []uint8 23 for i := 0; i < len(s); i++ { 24 list = append(list, s[i]) 25 } 26 return list 27 } 28 29 func (s ISCString) Count(substr string) int { 30 return strings.Count(string(s), substr) 31 } 32 33 func (s ISCString) Contains(substr string) bool { 34 return strings.Contains(string(s), substr) 35 } 36 37 func (s ISCString) ContainsAny(chars string) bool { 38 return strings.ContainsAny(string(s), chars) 39 } 40 41 func (s ISCString) ContainsRune(r rune) bool { 42 return strings.ContainsRune(string(s), r) 43 } 44 45 func (s ISCString) IndexOf(substr string) int { 46 return strings.Index(string(s), substr) 47 } 48 49 func (s ISCString) LastIndexOf(substr string) int { 50 return strings.LastIndex(string(s), substr) 51 } 52 53 func (s ISCString) IndexByteOf(c byte) int { 54 return strings.IndexByte(string(s), c) 55 } 56 57 func (s ISCString) IndexOfAny(chars string) int { 58 return strings.IndexAny(string(s), chars) 59 } 60 61 func (s ISCString) LastIndexOfAny(chars string) int { 62 return strings.LastIndexAny(string(s), chars) 63 } 64 65 func (s ISCString) LastIndexOfByte(c byte) int { 66 return strings.LastIndexByte(string(s), c) 67 } 68 69 func (s ISCString) SplitN(sep string, n int) []ISCString { 70 ss := strings.SplitN(string(s), sep, n) 71 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 72 return ISCString(item) 73 }) 74 } 75 76 func (s ISCString) SplitAfterN(sep string, n int) []ISCString { 77 ss := strings.SplitAfterN(string(s), sep, n) 78 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 79 return ISCString(item) 80 }) 81 } 82 83 func (s ISCString) Split(sep string) []ISCString { 84 ss := strings.Split(string(s), sep) 85 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 86 return ISCString(item) 87 }) 88 } 89 90 func (s ISCString) SplitAfter(sep string) []ISCString { 91 ss := strings.SplitAfter(string(s), sep) 92 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 93 return ISCString(item) 94 }) 95 } 96 97 func (s ISCString) Fields() []ISCString { 98 ss := strings.Fields(string(s)) 99 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 100 return ISCString(item) 101 }) 102 } 103 104 func (s ISCString) FieldsFunc(f func(rune) bool) []ISCString { 105 ss := strings.FieldsFunc(string(s), f) 106 return ListToMapFrom[string, ISCString](ss).Map(func(item string) ISCString { 107 return ISCString(item) 108 }) 109 } 110 111 func (s ISCString) StartsWith(prefix string) bool { 112 return strings.HasPrefix(string(s), prefix) 113 } 114 115 func (s ISCString) EndsWith(suffix string) bool { 116 return strings.HasSuffix(string(s), suffix) 117 } 118 119 func (s ISCString) Repeat(count int) ISCString { 120 return ISCString(strings.Repeat(string(s), count)) 121 } 122 123 func (s ISCString) TrimLeftFunc(f func(rune) bool) ISCString { 124 return ISCString(strings.TrimLeftFunc(string(s), f)) 125 } 126 127 func (s ISCString) TrimRightFunc(f func(rune) bool) ISCString { 128 return ISCString(strings.TrimRightFunc(string(s), f)) 129 } 130 131 func (s ISCString) TrimFunc(f func(rune) bool) ISCString { 132 return ISCString(strings.TrimFunc(string(s), f)) 133 } 134 135 func (s ISCString) IndexOfFunc(f func(rune) bool) int { 136 return strings.IndexFunc(string(s), f) 137 } 138 139 func (s ISCString) LastIndexOfFunc(f func(rune) bool) int { 140 return strings.LastIndexFunc(string(s), f) 141 } 142 143 func (s ISCString) Trim(cutset string) ISCString { 144 return ISCString(strings.Trim(string(s), cutset)) 145 } 146 147 func (s ISCString) TrimLeft(cutset string) ISCString { 148 return ISCString(strings.TrimLeft(string(s), cutset)) 149 } 150 151 func (s ISCString) TrimRight(cutset string) ISCString { 152 return ISCString(strings.TrimRight(string(s), cutset)) 153 } 154 155 func (s ISCString) TrimSpace() ISCString { 156 return ISCString(strings.TrimSpace(string(s))) 157 } 158 159 func (s ISCString) TrimPrefix(prefix string) ISCString { 160 return ISCString(strings.TrimPrefix(string(s), prefix)) 161 } 162 163 func (s ISCString) TrimSuffix(suffix string) ISCString { 164 return ISCString(strings.TrimSuffix(string(s), suffix)) 165 } 166 167 func (s ISCString) Replace(old, new string, n int) ISCString { 168 return ISCString(strings.Replace(string(s), old, new, n)) 169 } 170 171 func (s ISCString) ReplaceAll(old, new string) ISCString { 172 return ISCString(strings.ReplaceAll(string(s), old, new)) 173 } 174 175 func (s ISCString) EqualFold(t string) bool { 176 return strings.EqualFold(string(s), t) 177 } 178 179 func (s ISCString) ToUpper() ISCString { 180 return ISCString(strings.ToUpper(string(s))) 181 } 182 183 func (s ISCString) ToLower() ISCString { 184 return ISCString(strings.ToLower(string(s))) 185 } 186 187 func (s ISCString) ToTitle() ISCString { 188 return ISCString(strings.ToTitle(string(s))) 189 } 190 191 func (s ISCString) IsEmpty() bool { 192 return len(s) == 0 193 } 194 195 func (s ISCString) SubStringStart(AStartIndex int) ISCString { 196 return s[AStartIndex:] 197 } 198 199 func (s ISCString) SubStringStartEnd(AStartIndex, AEndIndex int) ISCString { 200 return s[AStartIndex:AEndIndex] 201 } 202 203 func (s ISCString) SubStringBefore(delimiter string) ISCString { 204 if i := s.IndexOf(delimiter); i != -1 { 205 return s[:i] 206 } else { 207 return s 208 } 209 } 210 211 func (s ISCString) SubStringAfter(delimiter string) ISCString { 212 if i := s.IndexOf(delimiter); i != -1 { 213 return s[i+len(delimiter):] 214 } else { 215 return s 216 } 217 } 218 219 func (s ISCString) SubStringBeforeLast(delimiter string) ISCString { 220 if i := s.LastIndexOf(delimiter); i != -1 { 221 return s[:i] 222 } else { 223 return s 224 } 225 } 226 227 func (s ISCString) SubStringAfterLast(delimiter string) ISCString { 228 if i := s.LastIndexOf(delimiter); i != -1 { 229 return s[i+len(delimiter):] 230 } else { 231 return s 232 } 233 } 234 235 func (s ISCString) Insert(index int, substr string) ISCString { 236 ss := string(s[:index]) + substr + string(s[index:]) 237 return ISCString(ss) 238 } 239 240 func (s ISCString) Delete(index int, count int) ISCString { 241 ss := string(s[:index]) + string(s[index+count:]) 242 return ISCString(ss) 243 } 244 245 func (s ISCString) Matches(pattern string) bool { 246 reg := regexp.MustCompile(pattern) 247 return reg.MatchString(string(s)) 248 } 249 250 func (s ISCString) Lines() []ISCString { 251 return s.Split("\n") 252 } 253 254 func (s ISCString) LinesNoEmpty() []ISCString { 255 return NewListWithList(s.Split("\n")).Filter(func(item ISCString) bool { 256 return !item.IsEmpty() 257 }) 258 } 259 260 func (s ISCString) ToBoolean() bool { 261 return s.ToLower() == "true" 262 } 263 264 func (s ISCString) ToInt() int { 265 return ToInt(s) 266 } 267 268 func (s ISCString) ToInt8() int8 { 269 return ToInt8(s) 270 } 271 272 func (s ISCString) ToInt16() int16 { 273 return ToInt16(s) 274 } 275 276 func (s ISCString) ToInt32() int32 { 277 return ToInt32(s) 278 } 279 280 func (s ISCString) ToInt64() int64 { 281 return ToInt64(s) 282 } 283 284 func (s ISCString) ToFloat() float32 { 285 return ToFloat32(s) 286 } 287 288 func (s ISCString) ToFloat64() float64 { 289 return ToFloat64(s) 290 } 291 292 func (s ISCString) ToIntRadix(radix int) (int64, error) { 293 if radix != 2 && radix != 8 && radix != 10 && radix != 16 { 294 return 0, fmt.Errorf("radix %d is not supported", radix) 295 } 296 size := strconv.IntSize 297 return strconv.ParseInt(string(s), radix, size) 298 } 299 300 func (s ISCString) ToJSONEncoded() ISCString { 301 return s.ReplaceAll("\\", "\\\\").ReplaceAll("\n", "\\n").ReplaceAll("\"", "\\\"") 302 } 303 304 func (s ISCString) ToMap() ISCMap[ISCString, ISCString] { 305 return ListToTripleFrom[ISCString, ISCString, ISCString](s.Split("&")).Associate(func(item ISCString) Pair[ISCString, ISCString] { 306 sa := item.Split("=") 307 return NewPair(sa[0], sa[1]) 308 }) 309 } 310 311 func (s ISCString) ToCookieMap() ISCMap[ISCString, ISCString] { 312 return ListToTripleFrom[ISCString, ISCString, ISCString](s.Split(";")).Associate(func(item ISCString) Pair[ISCString, ISCString] { 313 sa := item.TrimSpace().Split("=") 314 return NewPair(sa[0].TrimSpace(), sa[1].TrimSpace()) 315 }) 316 } 317 318 func (s ISCString) ToPair() Pair[ISCString, ISCString] { 319 sa := s.TrimSpace().Split("=") 320 return NewPair(sa[0].TrimSpace(), sa[1].TrimSpace()) 321 } 322 323 func (s ISCString) Drop(n int) ISCString { 324 return s[n:] 325 } 326 327 func (s ISCString) DropLast(n int) ISCString { 328 return s[:len(s)-n] 329 } 330 331 func (s ISCString) Take(n int) ISCString { 332 return s[:n] 333 } 334 335 func (s ISCString) TakeLast(n int) ISCString { 336 return s[len(s)-n:] 337 } 338 339 // BigCamel 小驼峰到大驼峰:首字母变成大写: dataBaseUser -> DateBaseUser 340 func BigCamel(word string) string { 341 if word == "" { 342 return "" 343 } 344 return strings.ToUpper(word[:1]) + word[1:] 345 } 346 347 // BigCamelToMiddleLine 大驼峰到中划线: DataBaseUser -> data-db-user 348 func BigCamelToMiddleLine(word string) string { 349 if word == "" { 350 return "" 351 } 352 return MiddleLine(BigCamelToSmallCamel(word)) 353 } 354 355 // BigCamelToPostUnder 大驼峰到后缀下划线: DataBaseUser -> data_base_user_ 356 func BigCamelToPostUnder(word string) string { 357 if word == "" { 358 return "" 359 } 360 return PostUnder(BigCamelToSmallCamel(word)) 361 } 362 363 // BigCamelToPrePostUnder 大驼峰到前后缀下划线: DataBaseUser -> _data_base_user_ 364 func BigCamelToPrePostUnder(word string) string { 365 if word == "" { 366 return "" 367 } 368 return PrePostUnder(BigCamelToSmallCamel(word)) 369 } 370 371 // BigCamelToPreUnder 大驼峰到前后缀下划线: DataBaseUser -> _data_base_user 372 func BigCamelToPreUnder(word string) string { 373 if word == "" { 374 return "" 375 } 376 return PreUnder(BigCamelToSmallCamel(word)) 377 } 378 379 // BigCamelToSmallCamel 大驼峰到小驼峰:首字母变成小写:DataBaseUser -> dataBaseUser 380 func BigCamelToSmallCamel(word string) string { 381 if word == "" { 382 return "" 383 } 384 return strings.ToLower(word[:1]) + word[1:] 385 } 386 387 // BigCamelToUnderLine 大驼峰到下划线:DataBaseUser -> data_base_user 388 func BigCamelToUnderLine(word string) string { 389 if word == "" { 390 return "" 391 } 392 return UnderLine(BigCamelToSmallCamel(word)) 393 } 394 395 // BigCamelToUpperMiddle 大驼峰到小写中划线:DataBaseUser -> DATA-BASE-USER 396 func BigCamelToUpperMiddle(word string) string { 397 if word == "" { 398 return "" 399 } 400 return UpperUnderMiddle(BigCamelToSmallCamel(word)) 401 } 402 403 // BigCamelToUpperUnder 大驼峰到大写下划线: DataBaseUser -> DATA_BASE_USER 404 func BigCamelToUpperUnder(word string) string { 405 if word == "" { 406 return "" 407 } 408 return UpperUnder(BigCamelToSmallCamel(word)) 409 } 410 411 // MiddleLine 小驼峰到中划线:dataBaseUser -> data-db-user 412 func MiddleLine(word string) string { 413 if word == "" { 414 return "" 415 } 416 reg, err := regexp.Compile("\\B[A-Z]") 417 if err != nil { 418 return word 419 } 420 421 subIndex := reg.FindAllStringSubmatchIndex(word, -1) 422 var lastIndex = 0 423 var result = "" 424 for i := 0; i < len(subIndex); i++ { 425 result += word[lastIndex:subIndex[i][0]] 426 result += "-" + strings.ToLower(word[subIndex[i][0]:subIndex[i][1]]) 427 lastIndex = subIndex[i][1] 428 } 429 result += word[lastIndex:] 430 return result 431 } 432 433 // MiddleLineToBigCamel 中划线到大驼峰:data-db-user -> DataBaseUser 434 func MiddleLineToBigCamel(word string) string { 435 if word == "" { 436 return "" 437 } 438 return BigCamel(MiddleLineToSmallCamel(word)) 439 } 440 441 // MiddleLineToSmallCamel 中划线到小驼峰:data-base-user -> dataBaseUser 442 func MiddleLineToSmallCamel(word string) string { 443 if word == "" { 444 return "" 445 } 446 return strings.ReplaceAll(ToUpperWord("(?<=-)[a-z]", word), "-", "") 447 } 448 449 // PostUnder 小驼峰到后下划线:dataBaseUser -> data_base_user_ 450 func PostUnder(word string) string { 451 if word == "" { 452 return "" 453 } 454 return UnderLine(word) + "_" 455 } 456 457 // PreFixUnderLine 小驼峰到添加前缀字符下划线:dataBaseUser -> pre_data_base_user 458 func PreFixUnderLine(word, preFix string) string { 459 return preFix + UnderLine(word) 460 } 461 462 // PreFixUnderToSmallCamel 前缀字符下划线去掉到小驼峰:pre_data_base_user -> dataBaseUser 463 func PreFixUnderToSmallCamel(word, preFix string) string { 464 if strings.HasPrefix(word, preFix) { 465 return UnderLineToSmallCamel(word[len(preFix):]) 466 } 467 return UnderLineToSmallCamel(word) 468 } 469 470 // PrePostUnder 小驼峰到前后缀下划线:dataBaseUser -> _data_base_user_ 471 func PrePostUnder(word string) string { 472 if word == "" { 473 return "" 474 } 475 return "_" + UnderLine(word) + "_" 476 } 477 478 // PreUnder 小驼峰到前下划线:dataBaseUser -> _data_base_user 479 func PreUnder(word string) string { 480 if word == "" { 481 return "" 482 } 483 return "_" + UnderLine(word) 484 } 485 486 // UnderLine 小驼峰到下划线:非边缘单词开头大写变前下划线和后面大写:dataBaseUser -> data_base_user 487 func UnderLine(word string) string { 488 if word == "" { 489 return "" 490 } 491 reg, err := regexp.Compile("\\B[A-Z]") 492 if err != nil { 493 return word 494 } 495 496 subIndex := reg.FindAllStringSubmatchIndex(word, -1) 497 var lastIndex = 0 498 var result = "" 499 for i := 0; i < len(subIndex); i++ { 500 result += word[lastIndex:subIndex[i][0]] 501 result += "_" + strings.ToLower(word[subIndex[i][0]:subIndex[i][1]]) 502 lastIndex = subIndex[i][1] 503 } 504 result += word[lastIndex:] 505 return result 506 } 507 508 // UnderLineToBigCamel 下划线到大驼峰:下划线后面小写变大写,下划线去掉 509 // data_base_user -> DataBaseUser 510 // _data_base_user -> DataBaseUser 511 // _data_base_user_ -> DataBaseUser 512 // data_base_user_ -> DataBaseUser 513 func UnderLineToBigCamel(word string) string { 514 if word == "" { 515 return "" 516 } 517 return BigCamel(strings.ReplaceAll(ToUpperWord("(?<=_)[a-z]", word), "_", "")) 518 } 519 520 // UnderLineToSmallCamel 下划线到小驼峰:下划线后面小写变大写,下划线去掉 521 // data_base_user -> dataBaseUser 522 // _data_base_user -> dataBaseUser 523 // _data_base_user_ -> dataBaseUser 524 // data_base_user_ -> dataBaseUser 525 func UnderLineToSmallCamel(word string) string { 526 if word == "" { 527 return "" 528 } 529 return BigCamelToSmallCamel(strings.ReplaceAll(ToUpperWord("(?<=_)[a-z]", word), "_", "")) 530 } 531 532 // 大写中划线到大驼峰:DATA-BASE-USER -> DataBaseUser 533 func UpperMiddleToBigCamel(word string) string { 534 return BigCamel(UpperUnderMiddleToSmallCamel(word)) 535 } 536 537 // UpperUnder 小驼峰到大写下划线:dataBaseUser -> DATA_BASE_USER 538 func UpperUnder(word string) string { 539 if word == "" { 540 return "" 541 } 542 reg, err := regexp.Compile("\\B[A-Z]") 543 if err != nil { 544 return word 545 } 546 547 subIndex := reg.FindAllStringSubmatchIndex(word, -1) 548 var lastIndex = 0 549 var result = "" 550 for i := 0; i < len(subIndex); i++ { 551 result += strings.ToUpper(word[lastIndex:subIndex[i][0]]) 552 result += "_" + strings.ToUpper(word[subIndex[i][0]:subIndex[i][1]]) 553 lastIndex = subIndex[i][1] 554 } 555 result += strings.ToUpper(word[lastIndex:]) 556 return result 557 } 558 559 // UpperUnderMiddle 小驼峰到大写中划线:dataBaseUser -> DATA-BASE-USER 560 func UpperUnderMiddle(word string) string { 561 if word == "" { 562 return "" 563 } 564 reg, err := regexp.Compile("\\B[A-Z]") 565 if err != nil { 566 return word 567 } 568 569 subIndex := reg.FindAllStringSubmatchIndex(word, -1) 570 var lastIndex = 0 571 var result = "" 572 for i := 0; i < len(subIndex); i++ { 573 result += strings.ToUpper(word[lastIndex:subIndex[i][0]]) 574 result += "-" + strings.ToUpper(word[subIndex[i][0]:subIndex[i][1]]) 575 lastIndex = subIndex[i][1] 576 } 577 result += strings.ToUpper(word[lastIndex:]) 578 return result 579 } 580 581 // UpperUnderMiddleToSmallCamel 大写中划线到大驼峰:DATA-BASE-USER -> dataBaseUser 582 func UpperUnderMiddleToSmallCamel(word string) string { 583 if word == "" { 584 return "" 585 } 586 return MiddleLineToSmallCamel(strings.ToLower(word)) 587 } 588 589 // UpperUnderToBigCamel 大写下划线到大驼峰:DATA_BASE_USER -> DataBaseUser 590 func UpperUnderToBigCamel(word string) string { 591 if word == "" { 592 return "" 593 } 594 return BigCamel(UpperUnderToSmallCamel(word)) 595 } 596 597 // UpperUnderToSmallCamel 大写下划线到小驼峰:DATA_BASE_USER -> dataBaseUser 598 func UpperUnderToSmallCamel(word string) string { 599 if word == "" { 600 return "" 601 } 602 return UnderLineToSmallCamel(strings.ToLower(word)) 603 } 604 605 // ToUpperWord 匹配的单词变为大写 606 // regex: 正则表达式,主要用于匹配某些字符变为大写 607 // word: 待匹配字段 608 func ToUpperWord(regex, word string) string { 609 if word == "" { 610 return "" 611 } 612 regexResult, err := regexp2.Compile(regex, 0) 613 if err != nil { 614 return word 615 } 616 617 matcherResult, err := regexResult.FindStringMatch(word) 618 if err != nil { 619 return word 620 } 621 622 var result = "" 623 var lastIndex = 0 624 for matcherResult != nil { 625 result += word[lastIndex:matcherResult.Index] 626 result += strings.ToUpper(word[matcherResult.Index : matcherResult.Index+1]) 627 lastIndex = matcherResult.Index + 1 628 matcherResult, err = regexResult.FindNextMatch(matcherResult) 629 if err != nil { 630 continue 631 } 632 } 633 result += word[lastIndex:] 634 return result 635 } 636 637 const ( 638 B = 1 639 KB = 1024 * B 640 MB = 1024 * KB 641 GB = 1024 * MB 642 TB = 1024 * GB 643 PB = 1024 * TB 644 EB = 1024 * PB 645 //ZB = 1024*EB 646 //YB = 1024*ZB 647 //BB = 1024*YB 648 ) 649 650 func FormatSize(fileSize int64) (size string) { 651 if fileSize < KB { 652 return fmt.Sprintf("%.2fB", float64(fileSize)/float64(B)) 653 } else if fileSize < MB { 654 return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(KB)) 655 } else if fileSize < GB { 656 return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(MB)) 657 } else if fileSize < TB { 658 return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(GB)) 659 } else if fileSize < PB { 660 return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(TB)) 661 } else if fileSize < EB { 662 return fmt.Sprintf("%.2fPB", float64(fileSize)/float64(PB)) 663 } else { 664 // 不要加更多判断了,编译器报错 665 return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(EB)) 666 } 667 } 668 669 func ParseByteSize(byteStr string) (size int64) { 670 if byteStr == "" { 671 return 0 672 } 673 674 if strings.HasSuffix(byteStr, "GB") { 675 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 676 return byteNum * GB 677 } 678 679 if strings.HasSuffix(byteStr, "MB") { 680 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 681 return byteNum * MB 682 } 683 684 if strings.HasSuffix(byteStr, "KB") { 685 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 686 return byteNum * KB 687 } 688 689 byteStr = strings.ToUpper(byteStr) 690 if strings.HasSuffix(byteStr, "EB") { 691 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 692 return byteNum * EB 693 } 694 695 if strings.HasSuffix(byteStr, "PB") { 696 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 697 return byteNum * PB 698 } 699 700 if strings.HasSuffix(byteStr, "TB") { 701 byteNum := ToInt64(byteStr[:len(byteStr)-2]) 702 return byteNum * TB 703 } 704 705 if strings.HasSuffix(byteStr, "B") { 706 byteNum := ToInt64(byteStr[:len(byteStr)-1]) 707 return byteNum * B 708 } 709 710 // 其他的暂时不支持 711 return 0 712 }