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 }