github.com/suiyunonghen/dxcommonlib@v0.0.0-20190612012041-7f8547a81a67/CommonFunc.go (about)

     1  /*
     2  公用包
     3  Autor: 不得闲
     4  QQ:75492895
     5   */
     6  package DxCommonLib
     7  
     8  import (
     9  	"golang.org/x/text/encoding/simplifiedchinese"
    10  	"golang.org/x/text/transform"
    11  	"bytes"
    12  	"io/ioutil"
    13  	"unsafe"
    14  	"os"
    15  	"time"
    16  	"strconv"
    17  	"unicode/utf16"
    18  	"encoding/binary"
    19  	"reflect"
    20  	"runtime"
    21  )
    22  
    23  type(
    24  	TDateTime  float64
    25  )
    26  
    27  const (
    28  	MinsPerHour = 60
    29  	MinsPerDay = 24 * MinsPerHour
    30  	SecsPerDay = MinsPerDay * 60
    31  	MSecsPerDay = SecsPerDay * 1000
    32  )
    33  var (
    34  	delphiFirstTime time.Time
    35  	IsAmd64 = runtime.GOARCH == "amd64"
    36  )
    37  
    38  func init() {
    39  	delphiFirstTime = time.Date(1899,12,30,0,0,0,0,time.Local)
    40  }
    41  
    42  //内存拷贝函数
    43  //go:linkname CopyMemory runtime.memmove
    44  func CopyMemory(to, from unsafe.Pointer, n uintptr)
    45  
    46  //清空内存
    47  //go:linkname ZeroMemory runtime.memclrNoHeapPointers
    48  func ZeroMemory(ptr unsafe.Pointer, n uintptr)
    49  
    50  //go:linkname memequal runtime.memequal
    51  func memequal(a, b unsafe.Pointer, size uintptr)bool
    52  
    53  //go:linkname memequal_varlen runtime.memequal_varlen
    54  func memequal_varlen(a, b unsafe.Pointer)bool
    55  
    56  //内存比较函数
    57  func CompareMem(a,b unsafe.Pointer,size int)bool  {
    58  	if size <= 0{
    59  		return memequal_varlen(a,b)
    60  	}
    61  	return memequal(a,b,uintptr(size))
    62  }
    63  
    64  func ZeroByteSlice(bt []byte)  {
    65  	btlen := len(bt)
    66  	if btlen > 0{
    67  		ZeroMemory(unsafe.Pointer(&bt[0]),uintptr(btlen))
    68  	}
    69  }
    70  
    71  /*
    72  从Delphi日期转为Go日期格式
    73  Delphi的日期规则为到1899-12-30号的天数+当前的毫秒数/一天的总共毫秒数集合
    74   */
    75  func (date TDateTime)ToTime()time.Time  {
    76  	mDay := time.Duration(date)
    77  	ms := (date - TDateTime(mDay)) * TDateTime(MSecsPerDay)
    78  	return delphiFirstTime.Add(mDay*time.Hour*24 + time.Duration(ms)*time.Millisecond)
    79  }
    80  
    81  func (date *TDateTime)WrapTime2Self(t time.Time)  {
    82  	days := t.Sub(delphiFirstTime) / (time.Hour * 24)
    83  	y,m,d := t.Date()
    84  	nowdate := time.Date(y,m,d,0,0,0,0,time.Local)
    85  	times := float64(t.Sub(nowdate))/float64(time.Hour*24)
    86  	*date = TDateTime(float64(days) + times)
    87  }
    88  
    89  func Time2DelphiTime(t *time.Time)TDateTime  {
    90  	days := t.Sub(delphiFirstTime) / (time.Hour * 24)
    91  	y,m,d := t.Date()
    92  	nowdate := time.Date(y,m,d,0,0,0,0,time.Local)
    93  	times := float64(t.Sub(nowdate))/float64(time.Hour*24)
    94  	return TDateTime(float64(days) + times)
    95  }
    96  
    97  func Ord(b bool)byte  {
    98  	if b{
    99  		return 1
   100  	}
   101  	return 0
   102  }
   103  
   104  func GBKString(str string)([]byte,error)  {
   105  	reader := bytes.NewReader([]byte(str))
   106  	O := transform.NewReader(reader, simplifiedchinese.GBK.NewEncoder())
   107  	d, e := ioutil.ReadAll(O)
   108  	if e != nil {
   109  		return nil,e
   110  	}
   111  	return d,nil
   112  }
   113  
   114  func GBK2Utf8(gbk []byte)([]byte,error){
   115  	reader := bytes.NewReader(gbk)
   116  	O := transform.NewReader(reader, simplifiedchinese.GBK.NewDecoder())
   117  	d, e := ioutil.ReadAll(O)
   118  	if e != nil {
   119  		return nil,e
   120  	}
   121  	return d,nil
   122  }
   123  
   124  func PcharLen(dstr uintptr)int  {
   125  	if dstr == 0{
   126  		return 0
   127  	}
   128  	ptr := unsafe.Pointer(dstr)
   129  	for i := 0; ; i++ {
   130  		if 0 == *(*uint16)(ptr) {
   131  			return int(i)
   132  		}
   133  		ptr = unsafe.Pointer(uintptr(ptr) + 2)
   134  	}
   135  	return 0
   136  }
   137  
   138  func DelphiPcharLen(dstr uintptr)(result int32)  {
   139  	//Delphi字符串的地址的-4地址位置为长度
   140  	if dstr == 0{
   141  		return 0
   142  	}
   143  	result = *(*int32)(unsafe.Pointer(dstr - 4))
   144  	return
   145  }
   146  
   147  //将常规的pchar返回到string
   148  func Pchar2String(pcharstr uintptr)string  {
   149  	if pcharstr == 0{
   150  		return ""
   151  	}
   152  	ptr := unsafe.Pointer(pcharstr)
   153  	gbt := make([]uint16,0,255)
   154  	for i := 0; ; i++ {
   155  		if 0 == *(*uint16)(ptr) {
   156  			break
   157  		}
   158  		gbt = append(gbt,*(*uint16)(ptr))
   159  		ptr = unsafe.Pointer(uintptr(ptr) + 2)
   160  	}
   161  	return string(utf16.Decode(gbt))
   162  }
   163  
   164  
   165  func FastPchar2String(pcharstr uintptr)string  {
   166  	if pcharstr==0{
   167  		return ""
   168  	}
   169  	s := new(reflect.SliceHeader)
   170  	s.Data = pcharstr
   171  	s.Len = PcharLen(pcharstr)
   172  	s.Cap = s.Len
   173  	return string(utf16.Decode(*(*[] uint16)(unsafe.Pointer(s))))
   174  }
   175  
   176  //将Delphi的Pchar转换到string,Unicode
   177  func DelphiPchar2String(dstr uintptr)string  {
   178  	if dstr == 0{
   179  		return ""
   180  	}
   181  	ptr := unsafe.Pointer(dstr)
   182  	gbt := make([]uint16,DelphiPcharLen(dstr))
   183  	for i := 0; ; i++ {
   184  		if 0 == *(*uint16)(ptr) {
   185  			break
   186  		}
   187  		gbt[i] = *(*uint16)(ptr)
   188  		ptr = unsafe.Pointer(uintptr(ptr) + 2)
   189  	}
   190  	return string(utf16.Decode(gbt))
   191  }
   192  
   193  func FastDelphiPchar2String(pcharstr uintptr)string  {
   194  	if pcharstr==0{
   195  		return ""
   196  	}
   197  	s := new(reflect.SliceHeader)
   198  	s.Data = pcharstr
   199  	s.Len = int(DelphiPcharLen(pcharstr)*2)
   200  	s.Cap = s.Len
   201  	return string(utf16.Decode(*(*[] uint16)(unsafe.Pointer(s))))
   202  }
   203  
   204  
   205  
   206  func FastBytes2Uint16s(bt []byte)[]uint16  {
   207  	sliceHead := (*reflect.SliceHeader)(unsafe.Pointer(&bt))
   208  	sliceHead.Len = sliceHead.Len / 2
   209  	sliceHead.Cap = sliceHead.Cap / 2
   210  	return *(*[]uint16)(unsafe.Pointer(sliceHead))
   211  }
   212  
   213  //本函数只作为强制转换使用,不可将返回的Slice再做修改处理
   214  func FastString2Byte(str string)[]byte  {
   215  	strHead := (*reflect.StringHeader)(unsafe.Pointer(&str))
   216  	var sliceHead reflect.SliceHeader
   217  	sliceHead.Len = strHead.Len
   218  	sliceHead.Data = strHead.Data
   219  	sliceHead.Cap = strHead.Len
   220  	return *(*[]byte)(unsafe.Pointer(&sliceHead))
   221  }
   222  
   223  func FastByte2String(bt []byte)string  {
   224  	return *(*string)(unsafe.Pointer(&bt))
   225  }
   226  
   227  func UTF16Byte2string(utf16bt []byte,isBigEnd bool)string  {
   228  	if !isBigEnd{
   229  		//判定末尾是否为换行,utf16,识别0
   230  		btlen := len(utf16bt)
   231  		if utf16bt[btlen-1] == 0 && utf16bt[btlen-2]=='\n'{
   232  			utf16bt = utf16bt[:btlen-2]
   233  			btlen -= 2
   234  		}else if utf16bt[btlen - 1] == '\n'{
   235  			utf16bt = utf16bt[:btlen-1]
   236  			btlen--
   237  		}
   238  		if utf16bt[btlen-1] == 0 && utf16bt[btlen-2]=='\r'{
   239  			utf16bt = utf16bt[:btlen-2]
   240  		}else if utf16bt[btlen - 1] == '\r'{
   241  			utf16bt = utf16bt[:btlen-1]
   242  			btlen--
   243  		}
   244  		return string(utf16.Decode(FastBytes2Uint16s(utf16bt)))
   245  	}
   246  	arrlen := len(utf16bt) / 2
   247  	uint16arr := make([]uint16,arrlen)
   248  	for j,i:=0,0;j<arrlen;j,i=j+1,i+2{
   249  		if j == arrlen-1{
   250  			if utf16bt[i]== '\r' || utf16bt[i+1]=='\r'{
   251  				arrlen--
   252  				break
   253  			}
   254  		}else{
   255  			uint16arr[j] = binary.BigEndian.Uint16(utf16bt[i:i+2])
   256  		}
   257  	}
   258  	return string(utf16.Decode(uint16arr[:arrlen]))
   259  }
   260  
   261  //将drwxrwx这些转化为 FileMode
   262  func ModePermStr2FileMode(permStr string)(result os.FileMode)  {
   263  	result = os.ModePerm
   264  	filemodebytes := []byte(permStr)
   265  	bytelen := len(filemodebytes)
   266  	istart := 0
   267  	if len(permStr) > 9 || filemodebytes[0]=='d' || filemodebytes[0]=='l' || filemodebytes[0]=='p'{
   268  		istart = 1
   269  	}
   270  	if bytelen > istart && filemodebytes[istart] == 'r'{
   271  		result = result | 0400
   272  	}else{
   273  		result = result & 0377
   274  	}
   275  	istart+=1
   276  	if bytelen > istart && filemodebytes[istart] == 'w'{
   277  		result = result | 0200
   278  	}else{
   279  		result = result & 0577
   280  	}
   281  	istart+=1
   282  
   283  	if bytelen > istart && filemodebytes[istart] == 'x'{
   284  		result = result | 0100
   285  	}else{
   286  		result = result & 0677
   287  	}
   288  	istart+=1
   289  
   290  	if bytelen > istart && filemodebytes[istart] == 'r'{
   291  		result = result | 0040
   292  	}else{
   293  		result = result & 0737
   294  	}
   295  	istart+=1
   296  
   297  	if bytelen > istart && filemodebytes[istart] == 'w'{
   298  		result = result | 0020
   299  	}else{
   300  		result = result & 0757
   301  	}
   302  	istart+=1
   303  
   304  	if bytelen > istart && filemodebytes[istart] == 'x'{
   305  		result = result | 0010
   306  	}else{
   307  		result = result & 0767
   308  	}
   309  	istart+=1
   310  
   311  
   312  	if bytelen > istart && filemodebytes[istart] == 'r'{
   313  		result = result | 0004
   314  	}else{
   315  		result = result & 0773
   316  	}
   317  	istart+=1
   318  
   319  	if bytelen > istart && filemodebytes[istart] == 'w'{
   320  		result = result | 0002
   321  	}else{
   322  		result = result & 0775
   323  	}
   324  	istart+=1
   325  
   326  	if bytelen > istart && filemodebytes[istart] == 'x'{
   327  		result = result | 0001
   328  	}else{
   329  		result = result & 0776
   330  	}
   331  
   332  
   333  	switch filemodebytes[0] {
   334  	case 'd': result = result | os.ModeDir
   335  	case 'l': result = result | os.ModeSymlink
   336  	case 'p': result = result | os.ModeNamedPipe
   337  	}
   338  	return
   339  }
   340  
   341  //Date(1402384458000)
   342  //Date(1224043200000+0800)
   343  func ParserJsonTime(jsontime string)TDateTime  {
   344  	bt := FastString2Byte(jsontime)
   345  	dtflaglen := 0
   346  	endlen := 0
   347  	if  bytes.HasPrefix(bt,[]byte{'D','a','t','e','('}) && bytes.HasSuffix(bt,[]byte{')'}){
   348  		dtflaglen = 5
   349  		endlen = 1
   350  	}else if bytes.HasPrefix(bt,[]byte{'/','D','a','t','e','('}) && bytes.HasSuffix(bt,[]byte{')','/'}){
   351  		dtflaglen = 6
   352  		endlen = 2
   353  	}
   354  	if dtflaglen > 0{
   355  		bt = bt[dtflaglen:len(bt)-endlen]
   356  		var(
   357  			ms int64
   358  			err error
   359  		)
   360  		endlen = 0
   361  		idx := bytes.IndexByte(bt,'+')
   362  		if idx < 0{
   363  			idx = bytes.IndexByte(bt,'-')
   364  		}else{
   365  			endlen = 1
   366  		}
   367  		if idx < 0{
   368  			str := FastByte2String(bt[:])
   369  			if ms,err = strconv.ParseInt(str,10,64);err != nil{
   370  				return -1
   371  			}
   372  			if len(str) > 9{
   373  				ms = ms / 1000
   374  			}
   375  		}else{
   376  			if endlen == 0{
   377  				endlen = -1
   378  			}
   379  			str := FastByte2String(bt[:idx])
   380  			ms,err = strconv.ParseInt(str,10,64)
   381  			if err != nil{
   382  				return -1
   383  			}
   384  			bt = bt[idx+1:]
   385  			if len(bt) < 2{
   386  				return -1
   387  			}
   388  			bt = bt[:2]
   389  			ctz,err := strconv.Atoi(FastByte2String(bt))
   390  			if err != nil{
   391  				return -1
   392  			}
   393  			if len(str) > 9{
   394  				ms = ms / 1000
   395  			}
   396  			ms += int64(ctz * 60)
   397  		}
   398  		ntime := time.Now()
   399  		ns := ntime.Unix()
   400  		ntime = ntime.Add((time.Duration(ms - ns)*time.Second))
   401  		return Time2DelphiTime(&ntime)
   402  	}
   403  	return -1
   404  }
   405  
   406  //将内容转义成Json字符串
   407  func EscapeJsonStr(str string) string {
   408  	var buf bytes.Buffer
   409  	for _,runedata := range str{
   410  		switch runedata {
   411  		case '\t':
   412  			buf.WriteByte('\\')
   413  			buf.WriteByte('t')
   414  		case '\f':
   415  			buf.WriteByte('\\')
   416  			buf.WriteByte('f')
   417  		case '\r':
   418  			buf.WriteByte('\\')
   419  			buf.WriteByte('r')
   420  		case '\n':
   421  			buf.WriteByte('\\')
   422  			buf.WriteByte('n')
   423  		case '\\':
   424  			buf.WriteByte('\\')
   425  			buf.WriteByte('\\')
   426  		case '"':
   427  			buf.WriteByte('\\')
   428  			buf.WriteByte('"')
   429  		case '\b':
   430  			buf.WriteByte('\\')
   431  			buf.WriteByte('b')
   432  			/*case '\'':
   433  				buf.WriteByte('\\')
   434  				buf.WriteByte('\'')
   435  			case '/':
   436  				buf.WriteByte('\\')
   437  				buf.WriteByte('/')*/
   438  		default:
   439  			if runedata < 256{
   440  				buf.WriteByte(byte(runedata))
   441  			}else{
   442  				buf.Write([]byte{'\\','u'})
   443  				var b [4]byte
   444  				binary.BigEndian.PutUint32(b[:],uint32(runedata))
   445  				if b[0]==0 && b[1] == 0{
   446  					hexstr := Binary2Hex(b[2:])
   447  					buf.WriteString(hexstr)
   448  				}else{
   449  					hexstr := Binary2Hex(b[0:2])
   450  					buf.WriteString(hexstr)
   451  					buf.Write([]byte{'\\','u'})
   452  					hexstr = Binary2Hex(b[2:])
   453  					buf.WriteString(hexstr)
   454  				}
   455  			}
   456  		}
   457  	}
   458  	return FastByte2String(buf.Bytes())
   459  }
   460  
   461  //解码转义字符,将"\u6821\u56ed\u7f51\t02%20得闲"这类字符串,解码成正常显示的字符串
   462  func ParserEscapeStr(bvalue []byte)string {
   463  	blen := len(bvalue)
   464  	i := 0
   465  	//IsInUnicode := false
   466  	unicodeidx := 0
   467  	//escapein := false
   468  	escapeType := uint8(0)  //0 normal,1 json\escapin,2 unicode escape, 3 % url escape
   469  	var buf bytes.Buffer
   470  	for i < blen{
   471  		switch escapeType {
   472  		case 1://json escapin
   473  			escapeType = 0
   474  			switch bvalue[i] {
   475  			case 't':
   476  				buf.WriteByte('\t')
   477  			case 'f':
   478  				buf.WriteByte('\f')
   479  			case 'r':
   480  				buf.WriteByte('\r')
   481  			case 'n':
   482  				buf.WriteByte('\n')
   483  			case '\\':
   484  				buf.WriteByte('\\')
   485  			case '"':
   486  				buf.WriteByte('"')
   487  			case 'b':
   488  				buf.WriteByte('\b')
   489  				/*case '\'':
   490  					buf.WriteByte('\'')
   491  				case '/':
   492  					buf.WriteByte('/')*/
   493  			case 'u':
   494  				escapeType = 2 // unicode decode
   495  				unicodeidx = i
   496  			default:
   497  				buf.WriteByte('\\')
   498  				buf.WriteByte(bvalue[i])
   499  			}
   500  		case 2: //unicode decode
   501  			if (bvalue[i]>='0' && bvalue[i] <= '9' || bvalue[i] >='a' && bvalue[i] <= 'f' ||
   502  				bvalue[i] >='A' && bvalue[i] <= 'F') && i - unicodeidx <= 4{
   503  				//还是正常的Unicode字符,4个字符为一组
   504  				//escapeType = 2
   505  			}else{
   506  				unicodestr := FastByte2String(bvalue[unicodeidx+1:i])
   507  				if arune,err := strconv.ParseInt(unicodestr,16,32);err==nil{
   508  					buf.WriteRune(rune(arune))
   509  				}else{
   510  					buf.Write(bvalue[unicodeidx:i])
   511  				}
   512  				escapeType = 0
   513  				continue
   514  			}
   515  		case 3: //url escape
   516  			for j := 0;j<3;j++{
   517  				if (bvalue[j+i]>='0' && bvalue[j+i] <= '9' || bvalue[i+j] >='a' && bvalue[i+j] <= 'f' ||
   518  					bvalue[j+i] >='A' && bvalue[j+i] <= 'F') && j<2{
   519  					//还是正常的Byte字符,2个字符为一组
   520  					//escapeType = 2
   521  				}else{
   522  					bytestr := FastByte2String(bvalue[i:i+j])
   523  					if abyte,err := strconv.ParseInt(bytestr,16,32);err==nil{
   524  						buf.WriteByte(byte(abyte))
   525  					}else{
   526  						buf.Write(bvalue[i-1:i+j]) //%要加上
   527  					}
   528  					escapeType = 0
   529  					i += j - 1
   530  					break
   531  				}
   532  			}
   533  		default: //normal
   534  			switch bvalue[i] {
   535  			case '\\':
   536  				escapeType = 1 //json escapin
   537  			case '%':
   538  				escapeType = 3 // url escape
   539  			default:
   540  				buf.WriteByte(bvalue[i])
   541  			}
   542  		}
   543  		i++
   544  	}
   545  	switch escapeType {
   546  	case 1:
   547  		buf.WriteByte('\\')
   548  	case 2:
   549  		unicodestr := FastByte2String(bvalue[unicodeidx+1:i])
   550  		if arune,err := strconv.ParseInt(unicodestr,16,32);err==nil{
   551  			buf.WriteRune(rune(arune))
   552  		}else{
   553  			buf.Write(bvalue[unicodeidx:i])
   554  		}
   555  	}
   556  	return FastByte2String(buf.Bytes())
   557  }
   558  
   559  
   560  //2进制转到16进制
   561  func Binary2Hex(bt []byte)string  {
   562  	var bf bytes.Buffer
   563  	vhex := [16]byte{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}
   564  	for _,vb := range bt{
   565  		bf.WriteByte(vhex[vb >> 4])
   566  		bf.WriteByte(vhex[vb & 0xF])
   567  	}
   568  	return FastByte2String(bf.Bytes())
   569  }
   570  
   571  //16进制到2进制
   572  func Hex2Binary(hexStr string)[]byte  {
   573  	if hexStr == ""{
   574  		return nil
   575  	}
   576  	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}
   577  	btlen := len(hexStr) / 2
   578  	result := make([]byte,btlen)
   579  	btlen = btlen << 1
   580  	jidx := 0
   581  	for i := 0;i<btlen;i += 2{
   582  		result[jidx] = vhex[hexStr[i]] << 4 | vhex[hexStr[i+1]]
   583  		jidx++
   584  	}
   585  	return result
   586  }