github.com/suiyunonghen/DxCommonLib@v0.5.3/strfuncs.go (about) 1 /* 2 公用包 3 Autor: 不得闲 4 QQ:75492895 5 */ 6 package DxCommonLib 7 8 import ( 9 "bytes" 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "golang.org/x/text/encoding/simplifiedchinese" 14 "golang.org/x/text/transform" 15 "io" 16 "math" 17 "os" 18 "reflect" 19 "strconv" 20 "strings" 21 "time" 22 "unicode" 23 "unicode/utf16" 24 "unicode/utf8" 25 "unsafe" 26 ) 27 28 //CopyMemory 内存拷贝函数 29 //go:linkname CopyMemory runtime.memmove 30 func CopyMemory(to, from unsafe.Pointer, n uintptr) 31 32 //ZeroMemory 清空内存 33 //go:linkname ZeroMemory runtime.memclrNoHeapPointers 34 func ZeroMemory(ptr unsafe.Pointer, n uintptr) 35 36 //go:linkname memequal runtime.memequal 37 func memequal(a, b unsafe.Pointer, size uintptr) bool 38 39 //go:linkname memequal_varlen runtime.memequal_varlen 40 func memequal_varlen(a, b unsafe.Pointer) bool 41 42 func Ord(x bool) uint8 { 43 // Avoid branches. In the SSA compiler, this compiles to 44 // exactly what you would want it to. 45 return *(*uint8)(unsafe.Pointer(&x)) 46 } 47 48 //CompareMem 内存比较函数 49 func CompareMem(a, b unsafe.Pointer, size int) bool { 50 if size <= 0 { 51 return memequal_varlen(a, b) 52 } 53 return memequal(a, b, uintptr(size)) 54 } 55 56 func ZeroByteSlice(bt []byte) { 57 btlen := len(bt) 58 if btlen > 0 { 59 ZeroMemory(unsafe.Pointer(&bt[0]), uintptr(btlen)) 60 } 61 } 62 63 func ReadAll(r io.Reader) ([]byte, error) { 64 b := make([]byte, 0, 512) 65 for { 66 if len(b) == cap(b) { 67 // Add more capacity (let append pick how much). 68 b = append(b, 0)[:len(b)] 69 } 70 n, err := r.Read(b[len(b):cap(b)]) 71 b = b[:len(b)+n] 72 if err != nil { 73 if err == io.EOF { 74 err = nil 75 } 76 return b, err 77 } 78 } 79 } 80 81 func GBKString(str string) ([]byte, error) { 82 reader := bytes.NewReader([]byte(str)) 83 O := transform.NewReader(reader, simplifiedchinese.GBK.NewEncoder()) 84 d, e := ReadAll(O) 85 if e != nil { 86 return nil, e 87 } 88 return d, nil 89 } 90 91 func GBK2Utf8(gbk []byte) ([]byte, error) { 92 reader := bytes.NewReader(gbk) 93 O := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder()) 94 d, e := ReadAll(O) 95 if e != nil { 96 return nil, e 97 } 98 return d, nil 99 } 100 101 func PcharLen(dstr uintptr) int { 102 if dstr == 0 { 103 return 0 104 } 105 ptr := unsafe.Pointer(dstr) 106 for i := 0; ; i++ { 107 if 0 == *(*uint16)(ptr) { 108 return int(i) 109 } 110 ptr = unsafe.Pointer(uintptr(ptr) + 2) 111 } 112 return 0 113 } 114 115 //Pchar2String 将常规的pchar返回到string 116 func Pchar2String(pcharstr uintptr) string { 117 if pcharstr == 0 { 118 return "" 119 } 120 ptr := unsafe.Pointer(pcharstr) 121 gbt := make([]uint16, 0, 255) 122 for i := 0; ; i++ { 123 if 0 == *(*uint16)(ptr) { 124 break 125 } 126 gbt = append(gbt, *(*uint16)(ptr)) 127 ptr = unsafe.Pointer(uintptr(ptr) + 2) 128 } 129 return string(utf16.Decode(gbt)) 130 } 131 132 func StringFromUtf16Pointer(utf16Addr uintptr, maxlen int) string { 133 if utf16Addr == 0 { 134 return "" 135 } 136 for i := 0; i < maxlen; i++ { 137 mb := (*uint16)(unsafe.Pointer(uintptr(uint(utf16Addr) + uint(i*2)))) 138 if *mb == 0 { 139 resultb := make([]uint16, i) 140 CopyMemory(unsafe.Pointer(&resultb[0]), unsafe.Pointer(utf16Addr), uintptr(i*2)) 141 return string(utf16.Decode(resultb)) 142 } 143 } 144 return "" 145 } 146 147 func FastPchar2String(pcharStr uintptr) string { 148 if pcharStr == 0 { 149 return "" 150 } 151 s := new(reflect.SliceHeader) 152 s.Data = pcharStr 153 s.Len = PcharLen(pcharStr) 154 s.Cap = s.Len 155 return string(utf16.Decode(*(*[]uint16)(unsafe.Pointer(s)))) 156 } 157 158 func FastPByte2ByteSlice(pByte uintptr, byteLen int) []byte { 159 s := new(reflect.SliceHeader) 160 s.Data = pByte 161 s.Len = byteLen 162 s.Cap = s.Len 163 return *(*[]byte)(unsafe.Pointer(s)) 164 } 165 166 //DelphiStringLen 获取Delphi字符串的长度 167 func DelphiStringLen(delphiString uintptr) (result int32) { 168 //Delphi字符串的地址的-4地址位置为长度 169 if delphiString == 0 { 170 return 0 171 } 172 result = *(*int32)(unsafe.Pointer(delphiString - 4)) 173 return 174 } 175 176 /* 177 FastDelphiString2String 将Delphi的字符串转为Go字符串 178 因为实际上Delphi的字符串,就是一个指针,这个指针的指向是数据位置,-4位置是长度,-8位置是引用计数,-10位置是每个字符占位个数,-12位置表示的是CodePage编码页 179 以上是对Unicode的Delphi的,如果是DXE之后的版本就只有到-8,有长度和引用计数,后面的都没有 180 */ 181 func FastDelphiString2String(delphiString uintptr, unicodeDelphi bool) string { 182 if delphiString == 0 { 183 return "" 184 } 185 dataLen := *(*int32)(unsafe.Pointer(delphiString - 4)) 186 if dataLen == 0 { 187 return "" 188 } 189 var codePage uint16 190 if unicodeDelphi { 191 codePage = *(*uint16)(unsafe.Pointer(delphiString - 12)) 192 } else { 193 codePage = 936 194 } 195 switch codePage { 196 case 1200: 197 //UTF16编码页 198 s := new(reflect.SliceHeader) 199 s.Data = delphiString 200 s.Len = int(dataLen * 2) 201 s.Cap = s.Len 202 return string(utf16.Decode(*(*[]uint16)(unsafe.Pointer(s)))) 203 case 65001: 204 //是UTF8的,那么直接开整 205 s := make([]byte, dataLen) 206 CopyMemory(unsafe.Pointer(&s[0]), unsafe.Pointer(delphiString), uintptr(dataLen)) 207 return *(*string)(unsafe.Pointer(&s)) 208 case 936, 20936: 209 //gbk的 210 s := new(reflect.SliceHeader) 211 s.Data = delphiString 212 s.Len = int(dataLen) 213 s.Cap = s.Len 214 if resultUtf8, err := GBK2Utf8(*(*[]byte)(unsafe.Pointer(s))); err == nil { 215 return *(*string)(unsafe.Pointer(&resultUtf8)) 216 } 217 case 950: 218 //繁体中文 219 } 220 return "" 221 } 222 223 func FastBytes2Uint16s(bt []byte) []uint16 { 224 sliceHead := (*reflect.SliceHeader)(unsafe.Pointer(&bt)) 225 sliceHead.Len = sliceHead.Len / 2 226 sliceHead.Cap = sliceHead.Cap / 2 227 return *(*[]uint16)(unsafe.Pointer(sliceHead)) 228 } 229 230 //FastString2Byte 本函数只作为强制转换使用,不可将返回的Slice再做修改处理 231 func FastString2Byte(str string) []byte { 232 strHead := (*reflect.StringHeader)(unsafe.Pointer(&str)) 233 var sliceHead reflect.SliceHeader 234 sliceHead.Len = strHead.Len 235 sliceHead.Data = strHead.Data 236 sliceHead.Cap = strHead.Len 237 return *(*[]byte)(unsafe.Pointer(&sliceHead)) 238 } 239 240 func StringData(str string) (uintptr, int) { 241 strHead := (*reflect.StringHeader)(unsafe.Pointer(&str)) 242 return strHead.Data, strHead.Len 243 } 244 245 func FastByte2String(bt []byte) string { 246 return *(*string)(unsafe.Pointer(&bt)) 247 } 248 249 //Utf8String 此函数的返回值不能修改 250 func Utf8String(utf8Data uintptr, utf8Len int) string { 251 var strHead reflect.StringHeader 252 strHead.Len = utf8Len 253 strHead.Data = utf8Data 254 return *(*string)(unsafe.Pointer(&strHead)) 255 } 256 257 //Buffer2ByteSlice 返回值不能修改 258 func Buffer2ByteSlice(Data uintptr, DataLen int) []byte { 259 var sliceHead reflect.SliceHeader 260 sliceHead.Len = DataLen 261 sliceHead.Data = Data 262 sliceHead.Cap = DataLen 263 return *(*[]byte)(unsafe.Pointer(&sliceHead)) 264 } 265 266 //ByteSliceIsPrintString 267 //判断二进制数组是否是可打印的字符串,如果打印字符的的百分比超过了指定的printPercent, 认为是可显示的Plaintext 268 //scanStyle 0 表示全扫描,1表示扫描头部10个rune,2表示扫描两头,3表示扫描前中尾 269 func ByteSliceIsPrintString(Data []byte, scanStyle byte) bool { 270 idx := 0 271 printC := 0 272 runeCount := 0 273 DataLen := len(Data) 274 if DataLen <= 30 { 275 scanStyle = 0 276 } 277 scanHead := func() bool { 278 for idx < DataLen && runeCount < 10 { 279 if r, l := utf8.DecodeRune(Data[idx:]); l > 0 { 280 idx += l 281 runeCount++ 282 if r == 13 || r == 10 || r == 9 || unicode.IsPrint(r) { 283 printC++ 284 } else if l != DataLen-1 { 285 //中间有不可显示的字符 286 return false 287 } 288 } else if l != DataLen-1 { 289 //不是最后一个,肯定不是一个有效的可显示的字符串了, 290 return false 291 } 292 } 293 return true 294 } 295 scanEnd := func() bool { 296 firstScan := true 297 firstDec := 0 298 idx = DataLen - 30 299 runeCount = 0 300 for idx < DataLen && runeCount < 10 { 301 if r, l := utf8.DecodeRune(Data[idx:]); l > 0 { 302 idx += l 303 runeCount++ 304 if r == 13 || r == 10 || r == 9 || unicode.IsPrint(r) { 305 printC++ 306 } else if l != DataLen-1 { 307 //中间有不可显示的字符 308 return false 309 } 310 } else if firstScan { 311 idx-- 312 firstDec++ 313 if firstDec > 3 { 314 return false 315 } 316 } else if l != DataLen-1 { 317 //不是最后一个,肯定不是一个有效的可显示的字符串了, 318 return false 319 } 320 } 321 return true 322 } 323 324 scanMid := func() bool { 325 firstScan := true 326 firstDec := 0 327 idx = DataLen/3 - 15 328 runeCount = 0 329 for idx < DataLen && runeCount < 10 { 330 if r, l := utf8.DecodeRune(Data[idx:]); l > 0 { 331 idx += l 332 runeCount++ 333 if r == 13 || r == 10 || r == 9 || unicode.IsPrint(r) { 334 printC++ 335 } else if l != DataLen-1 { 336 //中间有不可显示的字符 337 return false 338 } 339 } else if firstScan { 340 idx-- 341 firstDec++ 342 if firstDec > 3 { 343 return false 344 } 345 } else if l != DataLen-1 { 346 //不是最后一个,肯定不是一个有效的可显示的字符串了, 347 return false 348 } 349 } 350 return true 351 } 352 switch scanStyle { 353 case 0: 354 for idx < DataLen { 355 if r, l := utf8.DecodeRune(Data[idx:]); l > 0 { 356 idx += l 357 runeCount++ 358 if r == 13 || r == 10 || r == 9 || unicode.IsPrint(r) { 359 printC++ 360 } else if l != DataLen-1 { 361 //中间有不可显示的字符 362 return false 363 } 364 } else if l != DataLen-1 { 365 //不是最后一个,肯定不是一个有效的可显示的字符串了, 366 return false 367 } 368 } 369 case 1: 370 if !scanHead() { 371 return false 372 } 373 case 2: 374 //扫描前后 375 if !scanHead() { 376 return false 377 } 378 if !scanEnd() { 379 return false 380 } 381 case 3: 382 //扫描前中后 383 if !scanHead() { 384 return false 385 } 386 if !scanMid() { 387 return false 388 } 389 if !scanEnd() { 390 return false 391 } 392 } 393 if runeCount == 0 { 394 return true 395 } 396 percent := 100 * float32(printC/runeCount) 397 return percent >= 80 398 } 399 400 func UTF16Byte2string(utf16bt []byte, isBigEnd bool) string { 401 if !isBigEnd { 402 //判定末尾是否为换行,utf16,识别0 403 btlen := len(utf16bt) 404 if utf16bt[btlen-1] == 0 && utf16bt[btlen-2] == '\n' { 405 utf16bt = utf16bt[:btlen-2] 406 btlen -= 2 407 } else if utf16bt[btlen-1] == '\n' { 408 utf16bt = utf16bt[:btlen-1] 409 btlen-- 410 } 411 if utf16bt[btlen-1] == 0 && utf16bt[btlen-2] == '\r' { 412 utf16bt = utf16bt[:btlen-2] 413 } else if utf16bt[btlen-1] == '\r' { 414 utf16bt = utf16bt[:btlen-1] 415 btlen-- 416 } 417 return string(utf16.Decode(FastBytes2Uint16s(utf16bt))) 418 } 419 arrlen := len(utf16bt) / 2 420 uint16arr := make([]uint16, arrlen) 421 for j, i := 0, 0; j < arrlen; j, i = j+1, i+2 { 422 if j == arrlen-1 { 423 if utf16bt[i] == '\r' || utf16bt[i+1] == '\r' { 424 arrlen-- 425 break 426 } 427 } else { 428 uint16arr[j] = binary.BigEndian.Uint16(utf16bt[i : i+2]) 429 } 430 } 431 return string(utf16.Decode(uint16arr[:arrlen])) 432 } 433 434 func String2Utf16Byte(s string) ([]byte, error) { 435 bt, err := UTF16FromString(s) 436 if err != nil { 437 return nil, err 438 } 439 btlen := len(bt) * 2 440 result := make([]byte, btlen) 441 CopyMemory(unsafe.Pointer(&result[0]), unsafe.Pointer(&bt[0]), uintptr(btlen)) 442 return result, nil 443 } 444 445 func FastString2Utf16Byte(s string) ([]byte, error) { 446 bt, err := UTF16FromString(s) 447 if err != nil { 448 return nil, err 449 } 450 strHead := (*reflect.SliceHeader)(unsafe.Pointer(&bt)) 451 var sliceHead reflect.SliceHeader 452 sliceHead.Len = strHead.Len * 2 453 sliceHead.Data = strHead.Data 454 sliceHead.Cap = strHead.Cap * 2 455 return *(*[]byte)(unsafe.Pointer(&sliceHead)), nil 456 } 457 458 //ModePermStr2FileMode 将drwxrwx这些转化为 FileMode 459 func ModePermStr2FileMode(permStr string) (result os.FileMode) { 460 result = os.ModePerm 461 filemodebytes := []byte(permStr) 462 bytelen := len(filemodebytes) 463 istart := 0 464 if len(permStr) > 9 || filemodebytes[0] == 'd' || filemodebytes[0] == 'l' || filemodebytes[0] == 'p' { 465 istart = 1 466 } 467 if bytelen > istart && filemodebytes[istart] == 'r' { 468 result = result | 0400 469 } else { 470 result = result & 0377 471 } 472 istart += 1 473 if bytelen > istart && filemodebytes[istart] == 'w' { 474 result = result | 0200 475 } else { 476 result = result & 0577 477 } 478 istart += 1 479 480 if bytelen > istart && filemodebytes[istart] == 'x' { 481 result = result | 0100 482 } else { 483 result = result & 0677 484 } 485 istart += 1 486 487 if bytelen > istart && filemodebytes[istart] == 'r' { 488 result = result | 0040 489 } else { 490 result = result & 0737 491 } 492 istart += 1 493 494 if bytelen > istart && filemodebytes[istart] == 'w' { 495 result = result | 0020 496 } else { 497 result = result & 0757 498 } 499 istart += 1 500 501 if bytelen > istart && filemodebytes[istart] == 'x' { 502 result = result | 0010 503 } else { 504 result = result & 0767 505 } 506 istart += 1 507 508 if bytelen > istart && filemodebytes[istart] == 'r' { 509 result = result | 0004 510 } else { 511 result = result & 0773 512 } 513 istart += 1 514 515 if bytelen > istart && filemodebytes[istart] == 'w' { 516 result = result | 0002 517 } else { 518 result = result & 0775 519 } 520 istart += 1 521 522 if bytelen > istart && filemodebytes[istart] == 'x' { 523 result = result | 0001 524 } else { 525 result = result & 0776 526 } 527 528 switch filemodebytes[0] { 529 case 'd': 530 result = result | os.ModeDir 531 case 'l': 532 result = result | os.ModeSymlink 533 case 'p': 534 result = result | os.ModeNamedPipe 535 } 536 return 537 } 538 539 //EscapeJsonStr 将内容转义成Json字符串 540 func EscapeJsonStr(str string, EscapeUnicode bool) string { 541 return FastByte2String(EscapeJsonbyte(str, EscapeUnicode, nil)) 542 } 543 544 func EscapeJsonbyte(str string, EscapeUnicode bool, dst []byte) []byte { 545 dstlen := len(dst) 546 strlen := len(str) 547 if dstlen == 0 { 548 dst = make([]byte, 0, strlen*2) 549 } 550 for _, runedata := range str { 551 switch runedata { 552 case '\a': 553 dst = append(dst, '\\', 'a') 554 case '\b': 555 dst = append(dst, '\\', 'b') 556 case '\f': 557 dst = append(dst, '\\', 'f') 558 case '\n': 559 dst = append(dst, '\\', 'n') 560 case '\r': 561 dst = append(dst, '\\', 'r') 562 case '\t': 563 dst = append(dst, '\\', 't') 564 case '\v': 565 dst = append(dst, '\\', 'v') 566 case '\\': 567 dst = append(dst, '\\', '\\') 568 case '"': 569 dst = append(dst, '\\', '"') 570 /*case '\'': 571 dst = append(dst, '\\','\'')*/ 572 default: 573 if EscapeUnicode { 574 switch { 575 case runedata < utf8.RuneSelf: 576 dst = append(dst, byte(runedata)) 577 case runedata < ' ': 578 dst = append(dst, '\\', 'x') 579 dst = append(dst, vhex[byte(runedata)>>4], vhex[byte(runedata)&0xF]) 580 case runedata > utf8.MaxRune: 581 runedata = 0xFFFD 582 fallthrough 583 case runedata < 0x10000: 584 dst = append(dst, `\u`...) 585 for s := 12; s >= 0; s -= 4 { 586 dst = append(dst, vhex[runedata>>uint(s)&0xF]) 587 } 588 default: 589 dst = append(dst, `\U`...) 590 for s := 28; s >= 0; s -= 4 { 591 dst = append(dst, vhex[runedata>>uint(s)&0xF]) 592 } 593 } 594 } else { 595 if runedata < utf8.RuneSelf { 596 dst = append(dst, byte(runedata)) 597 } else { 598 l := len(dst) 599 dst = append(dst, 0, 0, 0, 0) 600 n := utf8.EncodeRune(dst[l:l+4], runedata) 601 dst = dst[:l+n] 602 } 603 } 604 } 605 } 606 return dst 607 } 608 609 func UnEscapeStr(bvalue []byte, unEscapeUrl bool, buf []byte) []byte { 610 blen := len(bvalue) 611 i := 0 612 unicodeidx := 0 613 escapeType := uint8(0) //0 normal,1 json\escapin,2 unicode escape, 3 % url escape 614 for i < blen { 615 switch escapeType { 616 case 1: //json escapin 617 escapeType = 0 618 switch bvalue[i] { 619 case 'n': 620 buf = append(buf, '\n') 621 case 'r': 622 buf = append(buf, '\r') 623 case 't': 624 buf = append(buf, '\t') 625 case 'a': 626 buf = append(buf, '\a') 627 case 'b': 628 buf = append(buf, '\b') 629 case 'f': 630 buf = append(buf, '\f') 631 case 'v': 632 buf = append(buf, '\v') 633 case '\\': 634 buf = append(buf, '\\') 635 case '"': 636 buf = append(buf, '"') 637 case '\'': 638 buf = append(buf, '\'') 639 case '/': 640 buf = append(buf, '/') 641 case 'u': 642 escapeType = 2 // unicode decode 643 unicodeidx = i 644 default: 645 buf = append(buf, '\\', bvalue[i]) 646 } 647 case 2: //unicode decode 648 if (bvalue[i] >= '0' && bvalue[i] <= '9' || bvalue[i] >= 'a' && bvalue[i] <= 'f' || 649 bvalue[i] >= 'A' && bvalue[i] <= 'F') && i-unicodeidx <= 4 { 650 //还是正常的Unicode字符,4个字符为一组 651 //escapeType = 2 652 } else { 653 unicodestr := FastByte2String(bvalue[unicodeidx+1 : i]) 654 if arune, err := strconv.ParseInt(unicodestr, 16, 32); err == nil { 655 l := len(buf) 656 buf = append(buf, 0, 0, 0, 0) 657 runelen := utf8.EncodeRune(buf[l:l+4], rune(arune)) 658 buf = buf[:l+runelen] 659 } else { 660 buf = append(buf, bvalue[unicodeidx:i]...) 661 } 662 escapeType = 0 663 continue 664 } 665 case 3: //url escape 666 for j := 0; j < 3; j++ { 667 curidx := j + i 668 if (curidx < blen) && (bvalue[curidx] >= '0' && bvalue[curidx] <= '9' || bvalue[curidx] >= 'a' && bvalue[curidx] <= 'f' || 669 bvalue[curidx] >= 'A' && bvalue[curidx] <= 'F') && j < 2 { 670 //还是正常的Byte字符,2个字符为一组 671 //escapeType = 2 672 } else { 673 if j < 2 { 674 buf = append(buf, bvalue[i-1:curidx]...) //%要加上 675 } else { 676 bytestr := FastByte2String(bvalue[i:curidx]) 677 if abyte, err := strconv.ParseInt(bytestr, 16, 32); err == nil { 678 if abyte < 0x20 || (abyte >= '0' && abyte <= '9' || abyte >= 'a' && abyte <= 'f' || 679 abyte >= 'A' && abyte <= 'F') { 680 buf = append(buf, bvalue[i-1:curidx]...) //%要加上 681 } else { 682 buf = append(buf, byte(abyte)) 683 } 684 } else { 685 buf = append(buf, bvalue[i-1:curidx]...) //%要加上 686 } 687 } 688 escapeType = 0 689 i += j - 1 690 break 691 } 692 } 693 default: //normal 694 switch bvalue[i] { 695 case '\\': 696 escapeType = 1 //json escapin 697 case '%': 698 if unEscapeUrl { 699 escapeType = 3 // url escape 700 } else { 701 buf = append(buf, bvalue[i]) 702 } 703 default: 704 buf = append(buf, bvalue[i]) 705 } 706 } 707 i++ 708 } 709 switch escapeType { 710 case 1: 711 buf = append(buf, '\\') 712 case 2: 713 unicodestr := FastByte2String(bvalue[unicodeidx+1 : i]) 714 if arune, err := strconv.ParseInt(unicodestr, 16, 32); err == nil { 715 l := len(buf) 716 buf = append(buf, 0, 0, 0, 0) 717 runelen := utf8.EncodeRune(buf[l:l+4], rune(arune)) 718 buf = buf[:l+runelen] 719 } else { 720 buf = append(buf, bvalue[unicodeidx:i]...) 721 } 722 case 3: 723 buf = append(buf, '%') 724 } 725 return buf 726 } 727 728 //ParserEscapeStr 解码转义字符,将"\u6821\u56ed\u7f51\t02%20得闲"这类字符串,解码成正常显示的字符串 729 func ParserEscapeStr(bvalue []byte, unEscapeUrl bool, buf []byte) string { 730 return FastByte2String(UnEscapeStr(bvalue, unEscapeUrl, buf)) 731 } 732 733 //ParserJsonTime2Go 734 //Date(1402384458000) 735 //Date(1224043200000+0800) 736 func ParserJsonTime2Go(jsontime string) time.Time { 737 bt := FastString2Byte(jsontime) 738 dtflaglen := 0 739 endlen := 0 740 if bytes.HasPrefix(bt, []byte{'D', 'a', 't', 'e', '('}) && bytes.HasSuffix(bt, []byte{')'}) { 741 dtflaglen = 5 742 endlen = 1 743 } else if bytes.HasPrefix(bt, []byte{'/', 'D', 'a', 't', 'e', '('}) && bytes.HasSuffix(bt, []byte{')', '/'}) { 744 dtflaglen = 6 745 endlen = 2 746 } 747 if dtflaglen > 0 { 748 bt = bt[dtflaglen : len(bt)-endlen] 749 var ( 750 ms int64 751 err error 752 ) 753 endlen = 0 754 idx := bytes.IndexByte(bt, '+') 755 if idx < 0 { 756 idx = bytes.IndexByte(bt, '-') 757 } else { 758 endlen = 1 759 } 760 if idx < 0 { 761 str := FastByte2String(bt[:]) 762 if ms, err = strconv.ParseInt(str, 10, 64); err != nil { 763 return time.Time{} 764 } 765 if len(str) > 9 { 766 ms = ms / 1000 767 } 768 } else { 769 if endlen == 0 { 770 endlen = -1 771 } 772 str := FastByte2String(bt[:idx]) 773 ms, err = strconv.ParseInt(str, 10, 64) 774 if err != nil { 775 return time.Time{} 776 } 777 bt = bt[idx+1:] 778 if len(bt) < 2 { 779 return time.Time{} 780 } 781 bt = bt[:2] 782 ctz, err := strconv.Atoi(FastByte2String(bt)) 783 if err != nil { 784 return time.Time{} 785 } 786 if len(str) > 9 { 787 ms = ms / 1000 788 } 789 ms += int64(ctz * 60) 790 } 791 ntime := time.Now() 792 ns := ntime.Unix() 793 ntime = ntime.Add((time.Duration(ms-ns) * time.Second)) 794 return ntime 795 } 796 return time.Time{} 797 } 798 799 var ( 800 vhex = [16]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'} 801 ) 802 803 //Binary2Hex 2进制转到16进制 804 func Binary2Hex(bt []byte, dst []byte) []byte { 805 l := len(dst) 806 if len(dst) == 0 { 807 dst = make([]byte, 0, l*2) 808 } 809 for _, vb := range bt { 810 dst = append(dst, vhex[vb>>4], vhex[vb&0xF]) 811 } 812 return dst 813 } 814 815 func Bin2Hex(bt []byte) string { 816 return FastByte2String(Binary2Hex(bt, nil)) 817 } 818 819 //Hex2Binary 16进制到2进制 820 func Hex2Binary(hexStr string) []byte { 821 if hexStr == "" { 822 return nil 823 } 824 vhex := ['G']byte{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15} 825 btlen := len(hexStr) / 2 826 result := make([]byte, btlen) 827 btlen = btlen << 1 828 jidx := 0 829 for i := 0; i < btlen; i += 2 { 830 result[jidx] = vhex[hexStr[i]]<<4 | vhex[hexStr[i+1]] 831 jidx++ 832 } 833 return result 834 } 835 836 //StrToIntDef From github.com/valyala/fastjson/tree/master/fastfloat 837 func StrToIntDef(vstr string, defv int64) int64 { 838 if v, err := ParseInt64(vstr); err != nil { 839 return defv 840 } else { 841 return v 842 } 843 } 844 845 func ParseInt64(s string) (int64, error) { 846 if len(s) == 0 { 847 return 0, errors.New("cannot parse int64 from empty string") 848 } 849 i := uint(0) 850 minus := s[0] == '-' 851 if minus { 852 i++ 853 if i >= uint(len(s)) { 854 return 0, fmt.Errorf("cannot parse int64 from %q", s) 855 } 856 } 857 858 d := int64(0) 859 j := i 860 for i < uint(len(s)) { 861 if s[i] >= '0' && s[i] <= '9' { 862 d = d*10 + int64(s[i]-'0') 863 i++ 864 if i > 18 { 865 // The integer part may be out of range for int64. 866 // Fall back to slow parsing. 867 dd, err := strconv.ParseInt(s, 10, 64) 868 if err != nil { 869 return 0, err 870 } 871 return dd, nil 872 } 873 continue 874 } 875 break 876 } 877 if i <= j { 878 return 0, fmt.Errorf("cannot parse int64 from %q", s) 879 } 880 if i < uint(len(s)) { 881 // Unparsed tail left. 882 return 0, fmt.Errorf("unparsed tail left after parsing int64 form %q: %q", s, s[i:]) 883 } 884 if minus { 885 d = -d 886 } 887 return d, nil 888 } 889 890 func ParseFloat(s string) (float64, error) { 891 if len(s) == 0 { 892 return 0, fmt.Errorf("cannot parse float64 from empty string") 893 } 894 slen := uint(len(s)) 895 i := uint(0) 896 minus := s[0] == '-' 897 if minus { 898 i++ 899 if i >= slen { 900 return 0, fmt.Errorf("cannot parse float64 from %q", s) 901 } 902 } 903 904 d := uint64(0) 905 j := i 906 for i < slen { 907 if s[i] >= '0' && s[i] <= '9' { 908 d = d*10 + uint64(s[i]-'0') 909 i++ 910 if i > 18 { 911 // The integer part may be out of range for uint64. 912 // Fall back to slow parsing. 913 f, err := strconv.ParseFloat(s, 64) 914 if err != nil && !math.IsInf(f, 0) { 915 return 0, err 916 } 917 return f, nil 918 } 919 continue 920 } 921 break 922 } 923 if i <= j { 924 ss := s[i:] 925 if strings.HasPrefix(ss, "+") { 926 ss = ss[1:] 927 } 928 if strings.EqualFold(ss, "inf") { 929 if minus { 930 return -inf, nil 931 } 932 return inf, nil 933 } 934 if strings.EqualFold(ss, "nan") { 935 return nan, nil 936 } 937 return 0, fmt.Errorf("unparsed tail left after parsing float64 from %q: %q", s, ss) 938 } 939 f := float64(d) 940 if i >= slen { 941 // Fast path - just integer. 942 if minus { 943 f = -f 944 } 945 return f, nil 946 } 947 948 if s[i] == '.' { 949 // Parse fractional part. 950 i++ 951 if i >= slen { 952 return 0, fmt.Errorf("cannot parse fractional part in %q", s) 953 } 954 k := i 955 for i < slen { 956 if s[i] >= '0' && s[i] <= '9' { 957 d = d*10 + uint64(s[i]-'0') 958 i++ 959 if i-j >= uint(len(float64pow10)) { 960 // The mantissa is out of range. Fall back to standard parsing. 961 f, err := strconv.ParseFloat(s, 64) 962 if err != nil && !math.IsInf(f, 0) { 963 return 0, fmt.Errorf("cannot parse mantissa in %q: %s", s, err) 964 } 965 return f, nil 966 } 967 continue 968 } 969 break 970 } 971 if i < k { 972 return 0, fmt.Errorf("cannot find mantissa in %q", s) 973 } 974 // Convert the entire mantissa to a float at once to avoid rounding errors. 975 f = float64(d) / float64pow10[i-k] 976 if i >= slen { 977 // Fast path - parsed fractional number. 978 if minus { 979 f = -f 980 } 981 return f, nil 982 } 983 } 984 if s[i] == 'e' || s[i] == 'E' { 985 // Parse exponent part. 986 i++ 987 if i >= slen { 988 return 0, fmt.Errorf("cannot parse exponent in %q", s) 989 } 990 expMinus := false 991 if s[i] == '+' || s[i] == '-' { 992 expMinus = s[i] == '-' 993 i++ 994 if i >= slen { 995 return 0, fmt.Errorf("cannot parse exponent in %q", s) 996 } 997 } 998 exp := int16(0) 999 j := i 1000 1001 for i < slen { 1002 if s[i] >= '0' && s[i] <= '9' { 1003 exp = exp*10 + int16(s[i]-'0') 1004 i++ 1005 if exp > 300 { 1006 // The exponent may be too big for float64. 1007 // Fall back to standard parsing. 1008 for k := i; k < slen; k++ { 1009 if s[k] < '0' || s[k] > '9' { 1010 return 0, fmt.Errorf("cannot parse float64 from %q", s) 1011 } 1012 } 1013 f, err := strconv.ParseFloat(s, 64) 1014 if err != nil && !math.IsInf(f, 0) { 1015 return 0, fmt.Errorf("cannot parse exponent in %q: %s", s, err) 1016 } 1017 return f, nil 1018 } 1019 continue 1020 } 1021 break 1022 } 1023 if i <= j { 1024 return 0, fmt.Errorf("cannot parse exponent in %q", s) 1025 } 1026 if expMinus { 1027 exp = -exp 1028 } 1029 f *= math.Pow10(int(exp)) 1030 if i >= uint(len(s)) { 1031 if minus { 1032 f = -f 1033 } 1034 return f, nil 1035 } 1036 } 1037 return 0, fmt.Errorf("cannot parse float64 from %q", s) 1038 } 1039 1040 //StrToUintDef From github.com/valyala/fastjson/tree/master/fastfloat 1041 func StrToUintDef(vstr string, defv uint64) uint64 { 1042 vlen := uint(len(vstr)) 1043 if vlen == 0 { 1044 return defv 1045 } 1046 if vlen > 18 { 1047 if dd, err := strconv.ParseUint(vstr, 10, 64); err != nil { 1048 return defv 1049 } else { 1050 return dd 1051 } 1052 } 1053 i := uint(0) 1054 d := uint64(0) 1055 j := i 1056 for i < vlen { 1057 if vstr[i] >= '0' && vstr[i] <= '9' { 1058 d = d*10 + uint64(vstr[i]-'0') 1059 i++ 1060 continue 1061 } 1062 break 1063 } 1064 if i <= j || i < vlen { 1065 return defv 1066 } 1067 return d 1068 } 1069 1070 var ( 1071 inf = math.Inf(1) 1072 nan = math.NaN() 1073 ) 1074 1075 var float64pow10 = [...]float64{ 1076 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e123, 1e124, 1077 } 1078 1079 //StrToFloatDef github.com/valyala/fastjson/tree/master/fastfloat 1080 func StrToFloatDef(s string, defv float64) float64 { 1081 vlen := uint(len(s)) 1082 if vlen == 0 { 1083 return defv 1084 } 1085 i := uint(0) 1086 minus := s[0] == '-' 1087 if minus { 1088 i++ 1089 if i >= vlen { 1090 return defv 1091 } 1092 } 1093 1094 d := uint64(0) 1095 j := i 1096 for i < vlen { 1097 if s[i] >= '0' && s[i] <= '9' { 1098 d = d*10 + uint64(s[i]-'0') 1099 i++ 1100 if i > 18 { 1101 // The integer part may be out of range for uint64. 1102 // Fall back to slow parsing. 1103 f, err := strconv.ParseFloat(s, 64) 1104 if err != nil && !math.IsInf(f, 0) { 1105 return defv 1106 } 1107 return f 1108 } 1109 continue 1110 } 1111 break 1112 } 1113 if i <= j { 1114 ss := s[i:] 1115 if strings.HasPrefix(ss, "+") { 1116 ss = ss[1:] 1117 } 1118 if strings.EqualFold(ss, "inf") { 1119 if minus { 1120 return -inf 1121 } 1122 return inf 1123 } 1124 if strings.EqualFold(ss, "nan") { 1125 return nan 1126 } 1127 return defv 1128 } 1129 f := float64(d) 1130 if i >= uint(len(s)) { 1131 // Fast path - just integer. 1132 if minus { 1133 f = -f 1134 } 1135 return f 1136 } 1137 1138 if s[i] == '.' { 1139 // Parse fractional part. 1140 i++ 1141 if i >= uint(len(s)) { 1142 return defv 1143 } 1144 k := i 1145 for i < uint(len(s)) { 1146 if s[i] >= '0' && s[i] <= '9' { 1147 d = d*10 + uint64(s[i]-'0') 1148 i++ 1149 if i-j >= uint(len(float64pow10)) { 1150 // The mantissa is out of range. Fall back to standard parsing. 1151 f, err := strconv.ParseFloat(s, 64) 1152 if err != nil && !math.IsInf(f, 0) { 1153 return defv 1154 } 1155 return f 1156 } 1157 continue 1158 } 1159 break 1160 } 1161 if i < k { 1162 return defv 1163 } 1164 // Convert the entire mantissa to a float at once to avoid rounding errors. 1165 f = float64(d) / float64pow10[i-k] 1166 if i >= uint(len(s)) { 1167 // Fast path - parsed fractional number. 1168 if minus { 1169 f = -f 1170 } 1171 return f 1172 } 1173 } 1174 if s[i] == 'e' || s[i] == 'E' { 1175 // Parse exponent part. 1176 i++ 1177 if i >= uint(len(s)) { 1178 return defv 1179 } 1180 expMinus := false 1181 if s[i] == '+' || s[i] == '-' { 1182 expMinus = s[i] == '-' 1183 i++ 1184 if i >= uint(len(s)) { 1185 return defv 1186 } 1187 } 1188 exp := int16(0) 1189 j := i 1190 for i < uint(len(s)) { 1191 if s[i] >= '0' && s[i] <= '9' { 1192 exp = exp*10 + int16(s[i]-'0') 1193 i++ 1194 if exp > 300 { 1195 // The exponent may be too big for float64. 1196 // Fall back to standard parsing. 1197 f, err := strconv.ParseFloat(s, 64) 1198 if err != nil && !math.IsInf(f, 0) { 1199 return defv 1200 } 1201 return f 1202 } 1203 continue 1204 } 1205 break 1206 } 1207 if i <= j { 1208 return defv 1209 } 1210 if expMinus { 1211 exp = -exp 1212 } 1213 f *= math.Pow10(int(exp)) 1214 if i >= uint(len(s)) { 1215 if minus { 1216 f = -f 1217 } 1218 return f 1219 } 1220 } 1221 return defv 1222 }