-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
hopeAbounds
committed
Apr 23, 2022
1 parent
b336e32
commit dec5791
Showing
15 changed files
with
1,062 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# env | ||
.idea/ | ||
|
||
# dependencies | ||
/node_modules | ||
|
||
# production | ||
/build | ||
|
||
# generated files | ||
.docusaurus | ||
.cache-loader | ||
|
||
# misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 周北海 | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,11 @@ | ||
# toolkit | ||
frequently used repetitive code. Some are my new ideas, and some are others' new ideas | ||
记录一些经常使用到的但是重复的代码,其中有一些是我的新想法,有一些是其他人的新想法。已发布 Go Modules,可以直接通过下述直接引入到自己的工程中。 | ||
|
||
```bash | ||
go install github.com/choubeihai/toolkit@latest | ||
``` | ||
|
||
## 感谢 | ||
|
||
- panjf2000 | ||
- smallnest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package byteconv | ||
|
||
import ( | ||
"reflect" | ||
"unsafe" | ||
) | ||
|
||
// BytesToString 在不需要额外内存分配的情况下,将字节切片转化为字符串 | ||
func BytesToString(b []byte) string { | ||
/* #nosec G103 */ | ||
return *(*string)(unsafe.Pointer(&b)) | ||
} | ||
|
||
// StringToBytes 在不需要额外内存分配的情况下,将字符串转化为字节切片 | ||
func StringToBytes(s string) (b []byte) { | ||
/* #nosec G103 */ | ||
sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) | ||
/* #nosec G103 */ | ||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) | ||
|
||
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len | ||
return b | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module github.com/hopeAbounds/toolkit | ||
|
||
go 1.17 | ||
|
||
require github.com/valyala/bytebufferpool v1.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= | ||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
package listbuffer | ||
|
||
import "github.com/hopeAbounds/toolkit/pool/bytebuffer" | ||
|
||
type ByteBuffer struct { | ||
Buf *bytebuffer.ByteBuffer | ||
next *ByteBuffer | ||
} | ||
|
||
// Len 返回 ByteBuffer 的长度 | ||
func (b *ByteBuffer) Len() int { | ||
if b.Buf == nil { | ||
return -1 | ||
} | ||
return b.Buf.Len() | ||
} | ||
|
||
// IsEmpty ByteBuffer是否为空 | ||
func (b *ByteBuffer) IsEmpty() bool { | ||
if b.Buf == nil { | ||
return true | ||
} | ||
return b.Buf.Len() == 0 | ||
} | ||
|
||
// ListBuffer is a linked list of ByteBuffer. | ||
type ListBuffer struct { | ||
bs [][]byte | ||
head *ByteBuffer | ||
tail *ByteBuffer | ||
size int | ||
bytes int64 // the total size of the link list of ByteBuffer | ||
} | ||
|
||
// Pop returns and removes the head of l. If l is empty, it returns nil. | ||
func (l *ListBuffer) Pop() *ByteBuffer { | ||
if l.head == nil { | ||
return nil | ||
} | ||
b := l.head | ||
l.head = b.next | ||
if l.head == nil { | ||
l.tail = nil | ||
} | ||
b.next = nil | ||
l.size-- | ||
l.bytes -= int64(b.Buf.Len()) | ||
return b | ||
} | ||
|
||
// PushFront adds the new node to the head of l. | ||
func (l *ListBuffer) PushFront(b *ByteBuffer) { | ||
if b == nil { | ||
return | ||
} | ||
if l.head == nil { | ||
b.next = nil | ||
l.tail = b | ||
} else { | ||
b.next = l.head | ||
} | ||
l.head = b | ||
l.size++ | ||
l.bytes += int64(b.Buf.Len()) | ||
} | ||
|
||
// PushBack adds a new node to the tail of l. | ||
func (l *ListBuffer) PushBack(b *ByteBuffer) { | ||
if b == nil { | ||
return | ||
} | ||
if l.tail == nil { | ||
l.head = b | ||
} else { | ||
l.tail.next = b | ||
} | ||
b.next = nil | ||
l.tail = b | ||
l.size++ | ||
l.bytes += int64(b.Buf.Len()) | ||
} | ||
|
||
// PushBytesFront is a wrapper of PushFront, which accepts []byte as its argument. | ||
func (l *ListBuffer) PushBytesFront(p []byte) { | ||
if len(p) == 0 { | ||
return | ||
} | ||
bb := bytebuffer.Get() | ||
_, _ = bb.Write(p) | ||
l.PushFront(&ByteBuffer{Buf: bb}) | ||
} | ||
|
||
// PushBytesBack is a wrapper of PushBack, which accepts []byte as its argument. | ||
func (l *ListBuffer) PushBytesBack(p []byte) { | ||
if len(p) == 0 { | ||
return | ||
} | ||
bb := bytebuffer.Get() | ||
_, _ = bb.Write(p) | ||
l.PushBack(&ByteBuffer{Buf: bb}) | ||
} | ||
|
||
// PeekBytesList assembles the [][]byte based on the list of ByteBuffer, | ||
// it won't remove these nodes from l until DiscardBytes() is called. | ||
func (l *ListBuffer) PeekBytesList() [][]byte { | ||
l.bs = l.bs[:0] | ||
for iter := l.head; iter != nil; iter = iter.next { | ||
l.bs = append(l.bs, iter.Buf.B) | ||
} | ||
return l.bs | ||
} | ||
|
||
// PeekBytesListWithBytes is like PeekBytesList but accepts [][]byte and puts them onto head. | ||
func (l *ListBuffer) PeekBytesListWithBytes(bs ...[]byte) [][]byte { | ||
l.bs = l.bs[:0] | ||
for _, b := range bs { | ||
if len(b) > 0 { | ||
l.bs = append(l.bs, b) | ||
} | ||
} | ||
for iter := l.head; iter != nil; iter = iter.next { | ||
l.bs = append(l.bs, iter.Buf.B) | ||
} | ||
return l.bs | ||
} | ||
|
||
// DiscardBytes removes some nodes based on n. | ||
func (l *ListBuffer) DiscardBytes(n int) { | ||
if n <= 0 { | ||
return | ||
} | ||
for n != 0 { | ||
b := l.Pop() | ||
if b == nil { | ||
break | ||
} | ||
if n < b.Len() { | ||
b.Buf.B = b.Buf.B[n:] | ||
l.PushFront(b) | ||
break | ||
} | ||
n -= b.Len() | ||
bytebuffer.Put(b.Buf) | ||
} | ||
} | ||
|
||
// Len returns the length of the list. | ||
func (l *ListBuffer) Len() int { | ||
return l.size | ||
} | ||
|
||
// Bytes returns the amount of bytes in this list. | ||
func (l *ListBuffer) Bytes() int64 { | ||
return l.bytes | ||
} | ||
|
||
// IsEmpty reports whether l is empty. | ||
func (l *ListBuffer) IsEmpty() bool { | ||
return l.head == nil | ||
} | ||
|
||
// Reset removes all elements from this list. | ||
func (l *ListBuffer) Reset() { | ||
for b := l.Pop(); b != nil; b = l.Pop() { | ||
bytebuffer.Put(b.Buf) | ||
} | ||
l.head = nil | ||
l.tail = nil | ||
l.size = 0 | ||
l.bytes = 0 | ||
l.bs = l.bs[:0] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package math | ||
|
||
const ( | ||
bitsize = 32 << (^uint(0) >> 63) // 64 | ||
maxintHeadBit = 1 << (bitsize - 2) | ||
) | ||
|
||
// IsPowerOfTwo 判断是否是2的幂次方 | ||
func IsPowerOfTwo(n int) bool { | ||
return n&(n-1) == 0 | ||
} | ||
|
||
// CeilToPowerOfTwo 返回数轴右侧离n最近的2的幂次方(大于等于n) | ||
func CeilToPowerOfTwo(n int) int { | ||
if n&maxintHeadBit != 0 && n > maxintHeadBit { | ||
panic("argument is too large") | ||
} | ||
if n <= 2 { | ||
return 2 | ||
} | ||
n-- | ||
n = fillBits(n) | ||
n++ | ||
return n | ||
} | ||
|
||
// FloorToPowerOfTwo 返回数轴左侧离n最近的2的幂次方(小于等于n) | ||
func FloorToPowerOfTwo(n int) int { | ||
if n <= 2 { | ||
return 2 | ||
} | ||
n = fillBits(n) | ||
n >>= 1 | ||
n++ | ||
return n | ||
} | ||
|
||
// | ||
func fillBits(n int) int { | ||
n |= n >> 1 | ||
n |= n >> 2 | ||
n |= n >> 4 | ||
n |= n >> 8 | ||
n |= n >> 16 | ||
n |= n >> 32 | ||
return n | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package bytebuffer | ||
|
||
import "github.com/valyala/bytebufferpool" | ||
|
||
// ByteBuffer 是bytebufferpool.ByteBuffer的别名. | ||
type ByteBuffer = bytebufferpool.ByteBuffer | ||
|
||
// Get 从pool中取出一个空的byte buffer | ||
var Get = bytebufferpool.Get | ||
|
||
// Put 向pool中归还 byte buffer | ||
var Put = func(b *ByteBuffer) { | ||
if b != nil { | ||
bytebufferpool.Put(b) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package byteslice | ||
|
||
import ( | ||
"math" | ||
"math/bits" | ||
"sync" | ||
) | ||
|
||
var builtinPool Pool | ||
|
||
// Pool 有32个sync.Pool,代表byte slice的长度(2的幂次方) | ||
type Pool struct { | ||
pools [32]sync.Pool | ||
} | ||
|
||
// Get 从builtinPool中返回一个长度为size的byte slice | ||
func Get(size int) []byte { | ||
return builtinPool.Get(size) | ||
} | ||
|
||
// Put 向builtinPool中归还byte slice | ||
func Put(buf []byte) { | ||
builtinPool.Put(buf) | ||
} | ||
|
||
func (p *Pool) Get(size int) []byte { | ||
if size <= 0 { | ||
return nil | ||
} | ||
if size > math.MaxInt32 { | ||
return make([]byte, size) | ||
} | ||
idx := index(uint32(size)) | ||
if v := p.pools[idx].Get(); v != nil { | ||
bp := v.(*[]byte) | ||
return (*bp)[:size] | ||
} | ||
return make([]byte, 1<<idx)[:size] | ||
} | ||
|
||
func (p *Pool) Put(buf []byte) { | ||
size := cap(buf) | ||
if size == 0 || size > math.MaxInt32 { | ||
return | ||
} | ||
idx := index(uint32(size)) | ||
if size != 1<<idx { // this byte slice is not from Pool.Get(), put it into the previous interval of idx | ||
idx-- | ||
} | ||
p.pools[idx].Put(&buf) | ||
} | ||
|
||
// index 返回长度为n字节的byte slice的Pool.pools下标 | ||
func index(n uint32) uint32 { | ||
return uint32(bits.Len32(n - 1)) | ||
} |
Oops, something went wrong.