mirror of
https://github.com/Monibuca/engine.git
synced 2025-10-07 09:30:56 +08:00
first commit
This commit is contained in:
73
util/SSE.go
Normal file
73
util/SSE.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
sseEent = []byte("event: ")
|
||||
sseBegin = []byte("data: ")
|
||||
sseEnd = []byte("\n\n")
|
||||
)
|
||||
|
||||
type SSE struct {
|
||||
http.ResponseWriter
|
||||
context.Context
|
||||
}
|
||||
|
||||
func (sse *SSE) Write(data []byte) (n int, err error) {
|
||||
if err = sse.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = sse.ResponseWriter.Write(sseBegin)
|
||||
n, err = sse.ResponseWriter.Write(data)
|
||||
_, err = sse.ResponseWriter.Write(sseEnd)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sse.ResponseWriter.(http.Flusher).Flush()
|
||||
return
|
||||
}
|
||||
|
||||
func (sse *SSE) WriteEvent(event string, data []byte) (err error) {
|
||||
if err = sse.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
_, err = sse.ResponseWriter.Write(sseEent)
|
||||
_, err = sse.ResponseWriter.Write([]byte(event))
|
||||
_, err = sse.ResponseWriter.Write([]byte("\n"))
|
||||
_, err = sse.Write(data)
|
||||
return
|
||||
}
|
||||
|
||||
func NewSSE(w http.ResponseWriter, ctx context.Context) *SSE {
|
||||
header := w.Header()
|
||||
header.Set("Content-Type", "text/event-stream")
|
||||
header.Set("Cache-Control", "no-cache")
|
||||
header.Set("Connection", "keep-alive")
|
||||
header.Set("X-Accel-Buffering", "no")
|
||||
header.Set("Access-Control-Allow-Origin", "*")
|
||||
return &SSE{
|
||||
w,
|
||||
ctx,
|
||||
}
|
||||
}
|
||||
|
||||
func (sse *SSE) WriteJSON(data interface{}) (err error) {
|
||||
var jsonData []byte
|
||||
if jsonData, err = json.Marshal(data); err == nil {
|
||||
if _, err = sse.Write(jsonData); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
func (sse *SSE) WriteExec(cmd *exec.Cmd) error {
|
||||
cmd.Stderr = sse
|
||||
cmd.Stdout = sse
|
||||
return cmd.Run()
|
||||
}
|
269
util/big_little_endian.go
Normal file
269
util/big_little_endian.go
Normal file
@@ -0,0 +1,269 @@
|
||||
package util
|
||||
|
||||
//
|
||||
// 注意:RTMP模式下都是大端模式
|
||||
//
|
||||
|
||||
var LittleEndian littleEndian
|
||||
|
||||
// BigEndian is the big-endian implementation of ByteOrder.
|
||||
var BigEndian bigEndian
|
||||
|
||||
// 低位字节排放在内存的低地址端,高位字节排放在内存的高地址端.
|
||||
type littleEndian struct{}
|
||||
|
||||
// b == 0x1234, b[0] == 0x12, b[1] == 0x34
|
||||
// b[0]低字节 b[1]高字节
|
||||
// 内存地址 低 -> 高
|
||||
// 0x34 0x12
|
||||
|
||||
// byte(v)低字节 b[0]内存低地址
|
||||
// byte(v>>8)高字节 b[1]内存高地址
|
||||
|
||||
// b == 2222 2222 1111 1111
|
||||
// b >> 8 -> 0000 0000 2222 2222
|
||||
// b << 8 -> 1111 1111 0000 0000
|
||||
|
||||
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
|
||||
func (littleEndian) Uint24(b []byte) uint32 { return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 }
|
||||
func (littleEndian) Uint32(b []byte) uint32 {
|
||||
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
|
||||
}
|
||||
func (littleEndian) Uint40(b []byte) uint64 {
|
||||
return uint64(b[0]) | uint64(b[1])<<8 |
|
||||
uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32
|
||||
}
|
||||
func (littleEndian) Uint48(b []byte) uint64 {
|
||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 |
|
||||
uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40
|
||||
}
|
||||
func (littleEndian) Uint64(b []byte) uint64 {
|
||||
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
|
||||
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
|
||||
}
|
||||
|
||||
//
|
||||
// Put
|
||||
//
|
||||
|
||||
func (littleEndian) PutUint16(b []byte, v uint16) {
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
}
|
||||
func (littleEndian) PutUint24(b []byte, v uint32) {
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
}
|
||||
func (littleEndian) PutUint32(b []byte, v uint32) {
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
}
|
||||
func (littleEndian) PutUint64(b []byte, v uint64) {
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
b[4] = byte(v >> 32)
|
||||
b[5] = byte(v >> 40)
|
||||
b[6] = byte(v >> 48)
|
||||
b[7] = byte(v >> 56)
|
||||
}
|
||||
|
||||
//
|
||||
// To
|
||||
//
|
||||
|
||||
func (littleEndian) ToUint16(v uint16) []byte {
|
||||
b := make([]byte, 2)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
return b
|
||||
}
|
||||
func (littleEndian) ToUint24(v uint32) []byte {
|
||||
b := make([]byte, 3)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
return b
|
||||
}
|
||||
func (littleEndian) ToUint32(v uint32) []byte {
|
||||
b := make([]byte, 4)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
return b
|
||||
}
|
||||
func (littleEndian) ToUint40(v uint64) []byte {
|
||||
b := make([]byte, 5)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
b[4] = byte(v >> 32)
|
||||
return b
|
||||
}
|
||||
func (littleEndian) ToUint48(v uint64) []byte {
|
||||
b := make([]byte, 6)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
b[4] = byte(v >> 32)
|
||||
b[5] = byte(v >> 40)
|
||||
return b
|
||||
}
|
||||
func (littleEndian) ToUint64(v uint64) []byte {
|
||||
b := make([]byte, 8)
|
||||
b[0] = byte(v)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 24)
|
||||
b[4] = byte(v >> 32)
|
||||
b[5] = byte(v >> 40)
|
||||
b[6] = byte(v >> 48)
|
||||
b[7] = byte(v >> 56)
|
||||
return b
|
||||
}
|
||||
|
||||
// 高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
|
||||
type bigEndian struct{}
|
||||
|
||||
// b == 0x1234, b[0] == 0x12, b[1] == 0x34
|
||||
// 内存地址 低 -> 高
|
||||
// 0x12 0x34
|
||||
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
|
||||
func (bigEndian) Uint24(b []byte) uint32 { return uint32(b[2]) | uint32(b[1])<<8 | uint32(b[0])<<16 }
|
||||
func (bigEndian) Uint32(b []byte) uint32 {
|
||||
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
|
||||
}
|
||||
func (bigEndian) Uint40(b []byte) uint64 {
|
||||
return uint64(b[4]) | uint64(b[3])<<8 |
|
||||
uint64(b[2])<<16 | uint64(b[1])<<24 | uint64(b[0])<<32
|
||||
}
|
||||
func (bigEndian) Uint48(b []byte) uint64 {
|
||||
return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 |
|
||||
uint64(b[2])<<24 | uint64(b[1])<<32 | uint64(b[0])<<40
|
||||
}
|
||||
func (bigEndian) Uint64(b []byte) uint64 {
|
||||
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
|
||||
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
|
||||
}
|
||||
|
||||
//
|
||||
// Put
|
||||
//
|
||||
|
||||
func (bigEndian) PutUint16(b []byte, v uint16) {
|
||||
b[0] = byte(v >> 8)
|
||||
b[1] = byte(v)
|
||||
}
|
||||
func (bigEndian) PutUint24(b []byte, v uint32) {
|
||||
b[0] = byte(v >> 16)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v)
|
||||
}
|
||||
func (bigEndian) PutUint32(b []byte, v uint32) {
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
}
|
||||
func (bigEndian) PutUint64(b []byte, v uint64) {
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
}
|
||||
|
||||
//
|
||||
// To
|
||||
//
|
||||
|
||||
func (bigEndian) ToUint16(v uint16) []byte {
|
||||
b := make([]byte, 2)
|
||||
b[0] = byte(v >> 8)
|
||||
b[1] = byte(v)
|
||||
return b
|
||||
}
|
||||
func (bigEndian) ToUint24(v uint32) []byte {
|
||||
b := make([]byte, 3)
|
||||
b[0] = byte(v >> 16)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v)
|
||||
return b
|
||||
}
|
||||
func (bigEndian) ToUint32(v uint32) []byte {
|
||||
b := make([]byte, 4)
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
return b
|
||||
}
|
||||
func (bigEndian) ToUint40(v uint64) []byte {
|
||||
b := make([]byte, 5)
|
||||
b[0] = byte(v >> 32)
|
||||
b[1] = byte(v >> 24)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 8)
|
||||
b[4] = byte(v)
|
||||
return b
|
||||
}
|
||||
func (bigEndian) ToUint48(v uint64) []byte {
|
||||
b := make([]byte, 6)
|
||||
b[0] = byte(v >> 40)
|
||||
b[1] = byte(v >> 32)
|
||||
b[2] = byte(v >> 24)
|
||||
b[3] = byte(v >> 16)
|
||||
b[4] = byte(v >> 8)
|
||||
b[5] = byte(v)
|
||||
return b
|
||||
}
|
||||
func (bigEndian) ToUint64(v uint64) []byte {
|
||||
b := make([]byte, 8)
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
return b
|
||||
}
|
||||
|
||||
//哥伦布解码
|
||||
func GetUev(buff []byte, start int) (value int, pos int) {
|
||||
l := len(buff)
|
||||
var nZeroNum uint = 0
|
||||
for start < l*8 {
|
||||
if (buff[start/8] & (0x80 >> uint(start%8))) > 0 {
|
||||
break
|
||||
}
|
||||
nZeroNum += 1
|
||||
start += 1
|
||||
}
|
||||
dwRet := 0
|
||||
start += 1
|
||||
var i uint
|
||||
for i = 0; i < nZeroNum; i++ {
|
||||
dwRet <<= 1
|
||||
if (buff[start/8] & (0x80 >> uint(start%8))) > 0 {
|
||||
dwRet += 1
|
||||
}
|
||||
start += 1
|
||||
}
|
||||
return (1 << nZeroNum) - 1 + dwRet, start
|
||||
}
|
||||
|
||||
func BigLittleSwap(v uint) uint {
|
||||
return (v >> 24) | ((v>>16)&0xff)<<8 | ((v>>8)&0xff)<<16 | (v&0xff)<<24
|
||||
}
|
118
util/bits/bits.go
Normal file
118
util/bits/bits.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package bits
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
R io.Reader
|
||||
n int
|
||||
bits uint64
|
||||
}
|
||||
|
||||
func (self *Reader) ReadBits64(n int) (bits uint64, err error) {
|
||||
if self.n < n {
|
||||
var b [8]byte
|
||||
var got int
|
||||
want := (n - self.n + 7) / 8
|
||||
if got, err = self.R.Read(b[:want]); err != nil {
|
||||
return
|
||||
}
|
||||
if got < want {
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
for i := 0; i < got; i++ {
|
||||
self.bits <<= 8
|
||||
self.bits |= uint64(b[i])
|
||||
}
|
||||
self.n += got * 8
|
||||
}
|
||||
bits = self.bits >> uint(self.n-n)
|
||||
self.bits ^= bits << uint(self.n-n)
|
||||
self.n -= n
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Reader) ReadBits(n int) (bits uint, err error) {
|
||||
var bits64 uint64
|
||||
if bits64, err = self.ReadBits64(n); err != nil {
|
||||
return
|
||||
}
|
||||
bits = uint(bits64)
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Reader) Read(p []byte) (n int, err error) {
|
||||
for n < len(p) {
|
||||
want := 8
|
||||
if len(p)-n < want {
|
||||
want = len(p) - n
|
||||
}
|
||||
var bits uint64
|
||||
if bits, err = self.ReadBits64(want * 8); err != nil {
|
||||
break
|
||||
}
|
||||
for i := 0; i < want; i++ {
|
||||
p[n+i] = byte(bits >> uint((want-i-1)*8))
|
||||
}
|
||||
n += want
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Writer struct {
|
||||
W io.Writer
|
||||
n int
|
||||
bits uint64
|
||||
}
|
||||
|
||||
func (self *Writer) WriteBits64(bits uint64, n int) (err error) {
|
||||
if self.n+n > 64 {
|
||||
move := uint(64 - self.n)
|
||||
mask := bits >> move
|
||||
self.bits = (self.bits << move) | mask
|
||||
self.n = 64
|
||||
if err = self.FlushBits(); err != nil {
|
||||
return
|
||||
}
|
||||
n -= int(move)
|
||||
bits ^= (mask << move)
|
||||
}
|
||||
self.bits = (self.bits << uint(n)) | bits
|
||||
self.n += n
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Writer) WriteBits(bits uint, n int) (err error) {
|
||||
return self.WriteBits64(uint64(bits), n)
|
||||
}
|
||||
|
||||
func (self *Writer) Write(p []byte) (n int, err error) {
|
||||
for n < len(p) {
|
||||
if err = self.WriteBits64(uint64(p[n]), 8); err != nil {
|
||||
return
|
||||
}
|
||||
n++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Writer) FlushBits() (err error) {
|
||||
if self.n > 0 {
|
||||
var b [8]byte
|
||||
bits := self.bits
|
||||
if self.n%8 != 0 {
|
||||
bits <<= uint(8 - (self.n % 8))
|
||||
}
|
||||
want := (self.n + 7) / 8
|
||||
for i := 0; i < want; i++ {
|
||||
b[i] = byte(bits >> uint((want-i-1)*8))
|
||||
}
|
||||
if _, err = self.W.Write(b[:want]); err != nil {
|
||||
return
|
||||
}
|
||||
self.n = 0
|
||||
}
|
||||
return
|
||||
}
|
51
util/bits/bits_test.go
Normal file
51
util/bits/bits_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package bits
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBits(t *testing.T) {
|
||||
rdata := []byte{0xf3, 0xb3, 0x45, 0x60}
|
||||
rbuf := bytes.NewReader(rdata[:])
|
||||
r := &Reader{R: rbuf}
|
||||
var u32 uint
|
||||
if u32, _ = r.ReadBits(4); u32 != 0xf {
|
||||
t.FailNow()
|
||||
}
|
||||
if u32, _ = r.ReadBits(4); u32 != 0x3 {
|
||||
t.FailNow()
|
||||
}
|
||||
if u32, _ = r.ReadBits(2); u32 != 0x2 {
|
||||
t.FailNow()
|
||||
}
|
||||
if u32, _ = r.ReadBits(2); u32 != 0x3 {
|
||||
t.FailNow()
|
||||
}
|
||||
b := make([]byte, 2)
|
||||
if r.Read(b); b[0] != 0x34 || b[1] != 0x56 {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
wbuf := &bytes.Buffer{}
|
||||
w := &Writer{W: wbuf}
|
||||
w.WriteBits(0xf, 4)
|
||||
w.WriteBits(0x3, 4)
|
||||
w.WriteBits(0x2, 2)
|
||||
w.WriteBits(0x3, 2)
|
||||
n, _ := w.Write([]byte{0x34, 0x56})
|
||||
if n != 2 {
|
||||
t.FailNow()
|
||||
}
|
||||
w.FlushBits()
|
||||
wdata := wbuf.Bytes()
|
||||
if wdata[0] != 0xf3 || wdata[1] != 0xb3 || wdata[2] != 0x45 || wdata[3] != 0x60 {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
b = make([]byte, 8)
|
||||
PutUInt64BE(b, 0x11223344, 32)
|
||||
if b[0] != 0x11 || b[1] != 0x22 || b[2] != 0x33 || b[3] != 0x44 {
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
22
util/bits/bufio/bufio.go
Normal file
22
util/bits/bufio/bufio.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package bufio
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
buf [][]byte
|
||||
R io.ReadSeeker
|
||||
}
|
||||
|
||||
func NewReaderSize(r io.ReadSeeker, size int) *Reader {
|
||||
buf := make([]byte, size*2)
|
||||
return &Reader{
|
||||
R: r,
|
||||
buf: [][]byte{buf[0:size], buf[size:]},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Reader) ReadAt(b []byte, off int64) (n int, err error) {
|
||||
return
|
||||
}
|
65
util/bits/golomb_reader.go
Normal file
65
util/bits/golomb_reader.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package bits
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type GolombBitReader struct {
|
||||
R io.Reader
|
||||
buf [1]byte
|
||||
left byte
|
||||
}
|
||||
|
||||
func (self *GolombBitReader) ReadBit() (res uint, err error) {
|
||||
if self.left == 0 {
|
||||
if _, err = self.R.Read(self.buf[:]); err != nil {
|
||||
return
|
||||
}
|
||||
self.left = 8
|
||||
}
|
||||
self.left--
|
||||
res = uint(self.buf[0]>>self.left) & 1
|
||||
return
|
||||
}
|
||||
|
||||
func (self *GolombBitReader) ReadBits(n int) (res uint, err error) {
|
||||
for i := 0; i < n; i++ {
|
||||
var bit uint
|
||||
if bit, err = self.ReadBit(); err != nil {
|
||||
return
|
||||
}
|
||||
res |= bit << uint(n-i-1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *GolombBitReader) ReadExponentialGolombCode() (res uint, err error) {
|
||||
i := 0
|
||||
for {
|
||||
var bit uint
|
||||
if bit, err = self.ReadBit(); err != nil {
|
||||
return
|
||||
}
|
||||
if !(bit == 0 && i < 32) {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
if res, err = self.ReadBits(i); err != nil {
|
||||
return
|
||||
}
|
||||
res += (1 << uint(i)) - 1
|
||||
return
|
||||
}
|
||||
|
||||
func (self *GolombBitReader) ReadSE() (res uint, err error) {
|
||||
if res, err = self.ReadExponentialGolombCode(); err != nil {
|
||||
return
|
||||
}
|
||||
if res&0x01 != 0 {
|
||||
res = (res + 1) / 2
|
||||
} else {
|
||||
res = -res / 2
|
||||
}
|
||||
return
|
||||
}
|
3
util/bits/pio/pio.go
Normal file
3
util/bits/pio/pio.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package pio
|
||||
|
||||
var RecommendBufioSize = 1024 * 64
|
121
util/bits/pio/reader.go
Normal file
121
util/bits/pio/reader.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package pio
|
||||
|
||||
func U8(b []byte) (i uint8) {
|
||||
return b[0]
|
||||
}
|
||||
|
||||
func U16BE(b []byte) (i uint16) {
|
||||
i = uint16(b[0])
|
||||
i <<= 8
|
||||
i |= uint16(b[1])
|
||||
return
|
||||
}
|
||||
|
||||
func I16BE(b []byte) (i int16) {
|
||||
i = int16(b[0])
|
||||
i <<= 8
|
||||
i |= int16(b[1])
|
||||
return
|
||||
}
|
||||
|
||||
func I24BE(b []byte) (i int32) {
|
||||
i = int32(int8(b[0]))
|
||||
i <<= 8
|
||||
i |= int32(b[1])
|
||||
i <<= 8
|
||||
i |= int32(b[2])
|
||||
return
|
||||
}
|
||||
|
||||
func U24BE(b []byte) (i uint32) {
|
||||
i = uint32(b[0])
|
||||
i <<= 8
|
||||
i |= uint32(b[1])
|
||||
i <<= 8
|
||||
i |= uint32(b[2])
|
||||
return
|
||||
}
|
||||
|
||||
func I32BE(b []byte) (i int32) {
|
||||
i = int32(int8(b[0]))
|
||||
i <<= 8
|
||||
i |= int32(b[1])
|
||||
i <<= 8
|
||||
i |= int32(b[2])
|
||||
i <<= 8
|
||||
i |= int32(b[3])
|
||||
return
|
||||
}
|
||||
|
||||
func U32LE(b []byte) (i uint32) {
|
||||
i = uint32(b[3])
|
||||
i <<= 8
|
||||
i |= uint32(b[2])
|
||||
i <<= 8
|
||||
i |= uint32(b[1])
|
||||
i <<= 8
|
||||
i |= uint32(b[0])
|
||||
return
|
||||
}
|
||||
|
||||
func U32BE(b []byte) (i uint32) {
|
||||
i = uint32(b[0])
|
||||
i <<= 8
|
||||
i |= uint32(b[1])
|
||||
i <<= 8
|
||||
i |= uint32(b[2])
|
||||
i <<= 8
|
||||
i |= uint32(b[3])
|
||||
return
|
||||
}
|
||||
|
||||
func U40BE(b []byte) (i uint64) {
|
||||
i = uint64(b[0])
|
||||
i <<= 8
|
||||
i |= uint64(b[1])
|
||||
i <<= 8
|
||||
i |= uint64(b[2])
|
||||
i <<= 8
|
||||
i |= uint64(b[3])
|
||||
i <<= 8
|
||||
i |= uint64(b[4])
|
||||
return
|
||||
}
|
||||
|
||||
func U64BE(b []byte) (i uint64) {
|
||||
i = uint64(b[0])
|
||||
i <<= 8
|
||||
i |= uint64(b[1])
|
||||
i <<= 8
|
||||
i |= uint64(b[2])
|
||||
i <<= 8
|
||||
i |= uint64(b[3])
|
||||
i <<= 8
|
||||
i |= uint64(b[4])
|
||||
i <<= 8
|
||||
i |= uint64(b[5])
|
||||
i <<= 8
|
||||
i |= uint64(b[6])
|
||||
i <<= 8
|
||||
i |= uint64(b[7])
|
||||
return
|
||||
}
|
||||
|
||||
func I64BE(b []byte) (i int64) {
|
||||
i = int64(int8(b[0]))
|
||||
i <<= 8
|
||||
i |= int64(b[1])
|
||||
i <<= 8
|
||||
i |= int64(b[2])
|
||||
i <<= 8
|
||||
i |= int64(b[3])
|
||||
i <<= 8
|
||||
i |= int64(b[4])
|
||||
i <<= 8
|
||||
i |= int64(b[5])
|
||||
i <<= 8
|
||||
i |= int64(b[6])
|
||||
i <<= 8
|
||||
i |= int64(b[7])
|
||||
return
|
||||
}
|
68
util/bits/pio/vec.go
Normal file
68
util/bits/pio/vec.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package pio
|
||||
|
||||
func VecLen(vec [][]byte) (n int) {
|
||||
for _, b := range vec {
|
||||
n += len(b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func VecSliceTo(in [][]byte, out [][]byte, s int, e int) (n int) {
|
||||
if s < 0 {
|
||||
s = 0
|
||||
}
|
||||
|
||||
if e >= 0 && e < s {
|
||||
panic("pio: VecSlice start > end")
|
||||
}
|
||||
|
||||
i := 0
|
||||
off := 0
|
||||
for s > 0 && i < len(in) {
|
||||
left := len(in[i])
|
||||
read := s
|
||||
if left < read {
|
||||
read = left
|
||||
}
|
||||
left -= read
|
||||
off += read
|
||||
s -= read
|
||||
e -= read
|
||||
if left == 0 {
|
||||
i++
|
||||
off = 0
|
||||
}
|
||||
}
|
||||
if s > 0 {
|
||||
panic("pio: VecSlice start out of range")
|
||||
}
|
||||
|
||||
for e != 0 && i < len(in) {
|
||||
left := len(in[i]) - off
|
||||
read := left
|
||||
if e > 0 && e < read {
|
||||
read = e
|
||||
}
|
||||
out[n] = in[i][off : off+read]
|
||||
n++
|
||||
left -= read
|
||||
e -= read
|
||||
off += read
|
||||
if left == 0 {
|
||||
i++
|
||||
off = 0
|
||||
}
|
||||
}
|
||||
if e > 0 {
|
||||
panic("pio: VecSlice end out of range")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func VecSlice(in [][]byte, s int, e int) (out [][]byte) {
|
||||
out = make([][]byte, len(in))
|
||||
n := VecSliceTo(in, out, s, e)
|
||||
out = out[:n]
|
||||
return
|
||||
}
|
21
util/bits/pio/vec_test.go
Normal file
21
util/bits/pio/vec_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package pio
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func ExampleVec() {
|
||||
vec := [][]byte{[]byte{1, 2, 3}, []byte{4, 5, 6, 7, 8, 9}, []byte{10, 11, 12, 13}}
|
||||
println(VecLen(vec))
|
||||
|
||||
vec = VecSlice(vec, 1, -1)
|
||||
fmt.Println(vec)
|
||||
|
||||
vec = VecSlice(vec, 2, -1)
|
||||
fmt.Println(vec)
|
||||
|
||||
vec = VecSlice(vec, 8, 8)
|
||||
fmt.Println(vec)
|
||||
|
||||
// Output:
|
||||
}
|
87
util/bits/pio/writer.go
Normal file
87
util/bits/pio/writer.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package pio
|
||||
|
||||
func PutU8(b []byte, v uint8) {
|
||||
b[0] = v
|
||||
}
|
||||
|
||||
func PutI16BE(b []byte, v int16) {
|
||||
b[0] = byte(v >> 8)
|
||||
b[1] = byte(v)
|
||||
}
|
||||
|
||||
func PutU16BE(b []byte, v uint16) {
|
||||
b[0] = byte(v >> 8)
|
||||
b[1] = byte(v)
|
||||
}
|
||||
|
||||
func PutI24BE(b []byte, v int32) {
|
||||
b[0] = byte(v >> 16)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v)
|
||||
}
|
||||
|
||||
func PutU24BE(b []byte, v uint32) {
|
||||
b[0] = byte(v >> 16)
|
||||
b[1] = byte(v >> 8)
|
||||
b[2] = byte(v)
|
||||
}
|
||||
|
||||
func PutI32BE(b []byte, v int32) {
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
}
|
||||
|
||||
func PutU32BE(b []byte, v uint32) {
|
||||
b[0] = byte(v >> 24)
|
||||
b[1] = byte(v >> 16)
|
||||
b[2] = byte(v >> 8)
|
||||
b[3] = byte(v)
|
||||
}
|
||||
|
||||
func PutU32LE(b []byte, v uint32) {
|
||||
b[3] = byte(v >> 24)
|
||||
b[2] = byte(v >> 16)
|
||||
b[1] = byte(v >> 8)
|
||||
b[0] = byte(v)
|
||||
}
|
||||
|
||||
func PutU40BE(b []byte, v uint64) {
|
||||
b[0] = byte(v >> 32)
|
||||
b[1] = byte(v >> 24)
|
||||
b[2] = byte(v >> 16)
|
||||
b[3] = byte(v >> 8)
|
||||
b[4] = byte(v)
|
||||
}
|
||||
|
||||
func PutU48BE(b []byte, v uint64) {
|
||||
b[0] = byte(v >> 40)
|
||||
b[1] = byte(v >> 32)
|
||||
b[2] = byte(v >> 24)
|
||||
b[3] = byte(v >> 16)
|
||||
b[4] = byte(v >> 8)
|
||||
b[5] = byte(v)
|
||||
}
|
||||
|
||||
func PutU64BE(b []byte, v uint64) {
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
}
|
||||
|
||||
func PutI64BE(b []byte, v int64) {
|
||||
b[0] = byte(v >> 56)
|
||||
b[1] = byte(v >> 48)
|
||||
b[2] = byte(v >> 40)
|
||||
b[3] = byte(v >> 32)
|
||||
b[4] = byte(v >> 24)
|
||||
b[5] = byte(v >> 16)
|
||||
b[6] = byte(v >> 8)
|
||||
b[7] = byte(v)
|
||||
}
|
384
util/convert.go
Normal file
384
util/convert.go
Normal file
@@ -0,0 +1,384 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
/*
|
||||
func ReadByteToUintX(r io.Reader, l int) (data uint64, err error) {
|
||||
if l%8 != 0 || l > 64 {
|
||||
return 0, errors.New("disable convert")
|
||||
}
|
||||
|
||||
bb := make([]byte, l)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
switch l / 8 {
|
||||
case 1:
|
||||
{
|
||||
return uint8(bb[0]), nil
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
return BigEndian.Uint16(bb), nil
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
return BigEndian.Uint24(bb), nil
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
return BigEndian.Uint32(bb), nil
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
//return BigEndian.Uint40(bb), nil
|
||||
return 0, errors.New("disable convert")
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
return BigEndian.Uint48(bb), nil
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
//return BigEndian.Uint56(bb), nil
|
||||
return 0, errors.New("disable convert")
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
return BigEndian.Uint64(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("convert not exist")
|
||||
}
|
||||
*/
|
||||
|
||||
// // 千万注意大小端,RTMP是大端
|
||||
func ByteToUint32N(data []byte) (ret uint32, err error) {
|
||||
if len(data) > 4 {
|
||||
return 0, errors.New("ByteToUint32N error!")
|
||||
}
|
||||
|
||||
for i := 0; i < len(data); i++ {
|
||||
ret <<= 8
|
||||
ret |= uint32(data[i])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// // 千万注意大小端,RTMP是大端
|
||||
func ByteToUint64N(data []byte) (ret uint64, err error) {
|
||||
if len(data) > 8 {
|
||||
return 0, errors.New("ByteToUint64N error!")
|
||||
}
|
||||
|
||||
for i := 0; i < len(data); i++ {
|
||||
ret <<= 8
|
||||
ret |= uint64(data[i])
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 千万注意大小端,RTMP是大端
|
||||
func ByteToUint32(data []byte, bigEndian bool) (ret uint32, err error) {
|
||||
if bigEndian {
|
||||
return BigEndian.Uint32(data), nil
|
||||
} else {
|
||||
return LittleEndian.Uint32(data), nil
|
||||
}
|
||||
}
|
||||
|
||||
func Uint32ToByte(data uint32, bigEndian bool) (ret []byte, err error) {
|
||||
if bigEndian {
|
||||
return BigEndian.ToUint32(data), nil
|
||||
} else {
|
||||
return LittleEndian.ToUint32(data), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadByteToUint8(r io.Reader) (data uint8, err error) {
|
||||
bb := make([]byte, 1)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint8(bb[0]), nil
|
||||
}
|
||||
|
||||
func ReadByteToUint16(r io.Reader, bigEndian bool) (data uint16, err error) {
|
||||
bb := make([]byte, 2)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint16(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint16(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadByteToUint24(r io.Reader, bigEndian bool) (data uint32, err error) {
|
||||
bb := make([]byte, 3)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint24(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint24(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadByteToUint32(r io.Reader, bigEndian bool) (data uint32, err error) {
|
||||
bb := make([]byte, 4)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint32(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint32(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadByteToUint40(r io.Reader, bigEndian bool) (data uint64, err error) {
|
||||
bb := make([]byte, 5)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint40(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint40(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
func ReadByteToUint48(r io.Reader, bigEndian bool) (data uint64, err error) {
|
||||
bb := make([]byte, 6)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint48(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint48(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func ReadByteToUint56(r io.Reader) (data uint64, err error) {
|
||||
bb := make([]byte, 7)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uint8(bb[0]), nil
|
||||
}
|
||||
*/
|
||||
|
||||
func ReadByteToUint64(r io.Reader, bigEndian bool) (data uint64, err error) {
|
||||
bb := make([]byte, 8)
|
||||
if _, err := io.ReadFull(r, bb); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if bigEndian {
|
||||
return BigEndian.Uint64(bb), nil
|
||||
} else {
|
||||
return LittleEndian.Uint64(bb), nil
|
||||
}
|
||||
}
|
||||
|
||||
func WriteUint8ToByte(w io.Writer, data uint8) error {
|
||||
bb := make([]byte, 8)
|
||||
bb[0] = byte(data)
|
||||
_, err := w.Write(bb[:1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint16ToByte(w io.Writer, data uint16, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint16(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint16(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint24ToByte(w io.Writer, data uint32, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint24(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint24(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint32ToByte(w io.Writer, data uint32, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint32(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint32(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint40ToByte(w io.Writer, data uint64, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint40(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint40(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint48ToByte(w io.Writer, data uint64, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint48(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint48(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteUint64ToByte(w io.Writer, data uint64, bigEndian bool) error {
|
||||
var bb []byte
|
||||
if bigEndian {
|
||||
bb = BigEndian.ToUint64(data)
|
||||
} else {
|
||||
bb = LittleEndian.ToUint64(data)
|
||||
}
|
||||
|
||||
_, err := w.Write(bb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPtsDts(v uint64) uint64 {
|
||||
// 4 + 3 + 1 + 15 + 1 + 15 + 1
|
||||
// 0011
|
||||
// 0010 + PTS[30-32] + marker_bit + PTS[29-15] + marker_bit + PTS[14-0] + marker_bit
|
||||
pts1 := ((v >> 33) & 0x7) << 30
|
||||
pts2 := ((v >> 17) & 0x7fff) << 15
|
||||
pts3 := ((v >> 1) & 0x7fff)
|
||||
|
||||
return pts1 | pts2 | pts3
|
||||
}
|
||||
|
||||
func PutPtsDts(v uint64) uint64 {
|
||||
// 4 + 3 + 1 + 15 + 1 + 15 + 1
|
||||
// 0011
|
||||
// 0010 + PTS[30-32] + marker_bit + PTS[29-15] + marker_bit + PTS[14-0] + marker_bit
|
||||
// 0x100010001
|
||||
// 0001 0000 0000 0000 0001 0000 0000 0000 0001
|
||||
// 3个 market_it
|
||||
pts1 := (v >> 30) & 0x7 << 33
|
||||
pts2 := (v >> 15) & 0x7fff << 17
|
||||
pts3 := (v & 0x7fff) << 1
|
||||
|
||||
return pts1 | pts2 | pts3 | 0x100010001
|
||||
}
|
||||
|
||||
func GetPCR(v uint64) uint64 {
|
||||
// program_clock_reference_base(33) + Reserved(6) + program_clock_reference_extension(9)
|
||||
base := v >> 15
|
||||
ext := v & 0x1ff
|
||||
return base*300 + ext
|
||||
}
|
||||
|
||||
func PutPCR(pcr uint64) uint64 {
|
||||
base := pcr / 300
|
||||
ext := pcr % 300
|
||||
return base<<15 | 0x3f<<9 | ext
|
||||
}
|
||||
|
||||
func GetFillBytes(data byte, n int) []byte {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = data
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
func ToFloat64(num interface{}) float64 {
|
||||
switch v := num.(type) {
|
||||
case uint:
|
||||
return float64(v)
|
||||
case int:
|
||||
return float64(v)
|
||||
case uint8:
|
||||
return float64(v)
|
||||
case uint16:
|
||||
return float64(v)
|
||||
case uint32:
|
||||
return float64(v)
|
||||
case uint64:
|
||||
return float64(v)
|
||||
case int8:
|
||||
return float64(v)
|
||||
case int16:
|
||||
return float64(v)
|
||||
case int32:
|
||||
return float64(v)
|
||||
case int64:
|
||||
return float64(v)
|
||||
case float64:
|
||||
return v
|
||||
case float32:
|
||||
return float64(v)
|
||||
}
|
||||
return 0
|
||||
}
|
126
util/crc32.go
Normal file
126
util/crc32.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
var Crc32_Table = []uint32{
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
|
||||
}
|
||||
|
||||
type Crc32Reader struct {
|
||||
R io.Reader
|
||||
Crc32 uint32
|
||||
}
|
||||
|
||||
type Crc32Writer struct {
|
||||
W io.Writer
|
||||
Crc32 uint32
|
||||
}
|
||||
|
||||
func (cr *Crc32Reader) Read(b []byte) (n int, err error) {
|
||||
if n, err = cr.R.Read(b); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cr.Crc32 = getCrc32(cr.Crc32, b)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (cr *Crc32Reader) ReadCrc32UIntAndCheck() (err error) {
|
||||
_, err = io.CopyN(ioutil.Discard, cr, 4)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cr.Crc32 != 0 {
|
||||
err = fmt.Errorf("crc32(%x) != 0", cr.Crc32)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (wr *Crc32Writer) Write(b []byte) (n int, err error) {
|
||||
if n, err = wr.W.Write(b); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
wr.Crc32 = getCrc32(wr.Crc32, b)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getCrc32(crc uint32, data []byte) uint32 {
|
||||
for _, v := range data {
|
||||
crc = Crc32_Table[v^byte(crc)] ^ (crc >> 8)
|
||||
}
|
||||
|
||||
return crc
|
||||
}
|
20
util/stderr.go
Normal file
20
util/stderr.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// +build linux
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logFile, err := os.OpenFile("./fatal.log", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
log.Println("服务启动出错", "打开异常日志文件失败", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 将进程标准出错重定向至文件,进程崩溃时运行时将向该文件记录协程调用栈信息
|
||||
syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
|
||||
}
|
40
util/util.go
Normal file
40
util/util.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// 检查文件或目录是否存在
|
||||
// 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false
|
||||
func Exist(filename string) bool {
|
||||
_, err := os.Stat(filename)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
|
||||
func ReadFileLines(filename string) (lines []string, err error) {
|
||||
file, err := os.OpenFile(filename, os.O_RDONLY, 0644)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
bio := bufio.NewReader(file)
|
||||
for {
|
||||
var line []byte
|
||||
|
||||
line, _, err = bio.ReadLine()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
file.Close()
|
||||
return lines, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
lines = append(lines, string(line))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
205
util/vecio.go
Normal file
205
util/vecio.go
Normal file
@@ -0,0 +1,205 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
|
||||
//"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
#include <sys/uio.h>
|
||||
// Structure for scatter/gather I/O.
|
||||
struct iovec{
|
||||
void *iov_base; // Pointer to data.
|
||||
size_t iov_len; // Length of data.
|
||||
};
|
||||
*/
|
||||
|
||||
type SysIOVec struct {
|
||||
Base uintptr
|
||||
Length uint64
|
||||
}
|
||||
|
||||
type IOVec struct {
|
||||
Data [][]byte
|
||||
Length int
|
||||
index int
|
||||
}
|
||||
|
||||
func (iov *IOVec) Append(b []byte) {
|
||||
iov.Data = append(iov.Data, b)
|
||||
iov.Length += len(b)
|
||||
}
|
||||
|
||||
// Data模型:
|
||||
// index -> | Data[0][0] | Data[0][1] | Data[0][2] | ... | Data[0][n] |
|
||||
// | Data[1][0] | Data[1][1] | Data[1][2] | ... | Data[1][n] |
|
||||
// ......
|
||||
// | Data[n][0] | Data[n][1] | Data[n][2] | ... | Data[n][n] |
|
||||
//
|
||||
// index是下标
|
||||
|
||||
func (iov *IOVec) WriteTo(w io.Writer, n int) (written int, err error) {
|
||||
for n > 0 && iov.Length > 0 {
|
||||
data := iov.Data[iov.index]
|
||||
|
||||
// 用来存放每次需要写入的数据
|
||||
var b []byte
|
||||
|
||||
// 只会读n个字节,超出n个字节,不管
|
||||
// 如果iov.Data里面有1000个数据,可是每次只读184个字节,那么剩下的数据(856)重新放回Data
|
||||
if n > len(data) {
|
||||
b = data
|
||||
} else {
|
||||
b = data[:n]
|
||||
}
|
||||
|
||||
// n个字节后面的数据
|
||||
// 如果这时候n个字节后面已经没有数据了,我们就将下标index往后移一位
|
||||
// 否则我们将n个字节后面的数据重新放回Data里.
|
||||
data = data[len(b):]
|
||||
if len(data) == 0 {
|
||||
iov.index++
|
||||
} else {
|
||||
iov.Data[iov.index] = data
|
||||
}
|
||||
|
||||
n -= len(b)
|
||||
iov.Length -= len(b)
|
||||
written += len(b)
|
||||
|
||||
if _, err = w.Write(b); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type IOVecWriter struct {
|
||||
fd uintptr
|
||||
smallBuffer []byte
|
||||
sysIOV []SysIOVec
|
||||
}
|
||||
|
||||
func NewIOVecWriter(w io.Writer) (iow *IOVecWriter) {
|
||||
var err error
|
||||
var file *os.File
|
||||
|
||||
// TODO:是否要增加其他的类型断言
|
||||
switch value := w.(type) {
|
||||
case *net.TCPConn:
|
||||
{
|
||||
file, err = value.File()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case *os.File:
|
||||
{
|
||||
file = value
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
iow = &IOVecWriter{
|
||||
fd: file.Fd(),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 1 2 3 4 5 6
|
||||
// --- -------------- --- --- --- -----------
|
||||
// | | | | | | | | | | | | ......
|
||||
// --- -------------- --- --- --- -----------
|
||||
//
|
||||
// 1 -> 5个字节, 3 -> 15个字节, 4 -> 10个字节, 5 -> 15个字节
|
||||
|
||||
// 1,3,4,5内存块太小(小于16个字节),因此我们将它组装起来为samllbuffer
|
||||
// 并且将Base置于每次组装smallBuffer前总长度的尾部.
|
||||
//
|
||||
// samllbuffer:
|
||||
// 1 3 4 5 ........
|
||||
// ------------------------------
|
||||
// | |
|
||||
// ------------------------------
|
||||
// <--> 第一个小内存块,假设地址为0xF10000
|
||||
// 5
|
||||
// <------> 第二个小内存块,假设地址为0xF20000
|
||||
// 20
|
||||
// <----------> 第三个小内存块,假设地址为0xF30000
|
||||
// 30
|
||||
// <--------------> 第四个小内存块,假设地址为0xF40000
|
||||
// 45
|
||||
//
|
||||
// 开始Base == 每次组装smallBuffer尾部
|
||||
// 即:
|
||||
// Base1 = 0, smallBuffer += 5,
|
||||
// Base3 = 5, smallBuffer += 15,
|
||||
// Base4 = 20, smallBuffer += 10,
|
||||
// Base5 = 30, smallBuffer += 15,
|
||||
//
|
||||
// 然后我们将每一块内存块都取出来,比samllBuffer小的内存块,我们就将Base指向内存块的地址
|
||||
// 之前小于16个字节的内存块,肯定会比smallBuffer小,因为smallBuffer是所有小内存快的总和.
|
||||
// 即:
|
||||
// Base1 = &smallBuffer[0], Base1 = 0xF10000,
|
||||
// Base3 = &smallBuffer[5], Base3 = 0xF20000,
|
||||
// Base4 = &smallBuffer[20], Base4 = 0xF30000,
|
||||
// Base5 = &smallBuffer[30], Base5 = 0xF40000,
|
||||
|
||||
func (iow *IOVecWriter) Write(data []byte) (written int, err error) {
|
||||
siov := SysIOVec{
|
||||
Length: uint64(len(data)),
|
||||
}
|
||||
|
||||
// unsafe.Pointer == void *
|
||||
// Base 用整数的形式来记录内存中有几个数据
|
||||
// 如果数据小于16,这个时候小块内存的Base还不是数据的内存地址
|
||||
if siov.Length < 16 {
|
||||
// Base 置于上一块samllBuffer的末尾
|
||||
// 然后拼接smallBuffer
|
||||
siov.Base = uintptr(len(iow.smallBuffer))
|
||||
iow.smallBuffer = append(iow.smallBuffer, data...)
|
||||
} else {
|
||||
siov.Base = uintptr(unsafe.Pointer(&data[0]))
|
||||
}
|
||||
|
||||
iow.sysIOV = append(iow.sysIOV, siov)
|
||||
|
||||
return written, nil
|
||||
}
|
||||
|
||||
func (iow *IOVecWriter) Flush() error {
|
||||
// 取出每一块内存
|
||||
for i, _ := range iow.sysIOV {
|
||||
siov := &iow.sysIOV[i] // 一定要拿地址,如果这里不是取地址,那么无法改变下面Base的值
|
||||
if siov.Base < uintptr(len(iow.smallBuffer)) {
|
||||
// 这个时候小块内存的Base就是数据的内存地址
|
||||
siov.Base = uintptr(unsafe.Pointer(&iow.smallBuffer[siov.Base]))
|
||||
}
|
||||
}
|
||||
|
||||
N := 1024
|
||||
count := len(iow.sysIOV)
|
||||
// 每次最多取1024个内存块(不管是大内存块,还是小内存块)
|
||||
for i := 0; i < count; i += N {
|
||||
n := count - i
|
||||
if n > N {
|
||||
n = N
|
||||
}
|
||||
|
||||
// _, _, errno := syscall.Syscall(syscall.SYS_WRITEV, iow.fd, uintptr(unsafe.Pointer(&iow.sysIOV[i])), uintptr(n))
|
||||
// if errno != 0 {
|
||||
// return errors.New(errno.Error())
|
||||
// }
|
||||
}
|
||||
|
||||
iow.sysIOV = iow.sysIOV[:0]
|
||||
iow.smallBuffer = iow.smallBuffer[:0]
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user