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  }