golang 링 버퍼 구현 (길이 부정)

모든 패 킷 은 ringbuffer 의 저장 구 조 를 기록 합 니 다:
     packet_size:uint16 | packet_ctx:byte[ ]
     전체 링 버퍼 의 구조:
    ----------
    packet1
    ----------
    packet2    
    --------
    ……
type Ringbuffer struct{
	start,use int
	buf []byte 
}

       ringbuffer 에서 buf 는 데이터 내용 을 저장 하고 start 는 읽 는 위치의 index 이 며 use 는 ringbuffer 에서 읽 지 않 은 패 킷 의 바이트 수, start + 입 니 다.
use 는 바로 쓴 위치 입 니 다.
      실현 요점 1: 돌아 가기
      ringbuffer 는 링 입 니 다. 끝 에 기록 한 후에 끝 부분 으로 돌아 가 야 합 니 다. 패 킷 의 크기 가 정 해 지지 않 기 때문에 끝 부분 에 도착 하면 숫자 가 나타 날 수 있 습 니 다.
가방 의 반 은 끝 에 있 고 반 은 시작 에 있 으 며 읽 을 때 패 킷 의 반 은 끝 에 있 고 반 은 시작 에 합 쳐 야 합 니 다.
     구현 요점 2: 기록 이 너무 빠 르 고 덮어 쓰기 해제
     쓰기 속도 가 읽 기 속도 보다 클 때 새 쓰기 데 이 터 는 읽 지 않 은 데이터 와 겹 쳐 집 니 다. 그러면 두 가지 결정 이 있 습 니 다. 읽 지 않 은 데 이 터 를 덮어 쓰 고 새 데 이 터 를 버 리 는 것 입 니 다.
데 이 터 를 기록 하 다.
     구현 요점 3: 중복 읽 기 방지
     ringbuffer 는 덮어 쓰기 데 이 터 를 통 해 읽 지 않 은 데 이 터 를 삭제 하지 않 기 때문에 ringbuffer 의 use 를 통 해 읽 지 않 은 데 이 터 를 판단 합 니 다.
데이터
package ringbuffer
import(
	"fmt"
)
type Ringbuffer struct{
	start,use int
	buf []byte 
}
func IntToByte(n int) []byte{
	buf:=make([]byte,4)
    buf[3] =  (byte)((n>>24) & 0xFF) 
    buf[2] =  (byte)((n>>16) & 0xFF)  
    buf[1] =  (byte)((n>>8) & 0xFF)    
    buf[0] =  (byte)(n & 0xFF);  
	return buf
}
func ByteToInt(buf []byte) int{
	var value int    
    value = (int)((buf[0] & 0xFF)|((buf[1] & 0xFF)<<8)|((buf[2] & 0xFF)<<16)|((buf[3] & 0xFF)<<24))
    return value; 
}
func NewRingbuffer(size int) *Ringbuffer{
	return &Ringbuffer{0,0,make([]byte,size)}
}//         
func (r *Ringbuffer) WriteCover(b []byte) bool {
	block_size:=len(b)
	if block_size > 0 {
		size:=len(r.buf)
		start:=(r.start+r.use)%size
		size_byte:= IntToByte(block_size)
        /*         block,
		     ,  r.start */
		flag:=block_size+len(size_byte)
		for flag > (r.start-start+size)%size &&r.use!=0 {
			rblock_size:= ByteToInt(r.buf[r.start:r.start+4])			
			r.start = (r.start + rblock_size + 4)%size
		}
		//  block   
		n:=copy(r.buf[start:],size_byte)
		if start+len(size_byte) > len(r.buf){
			copy(r.buf,size_byte[n:])//        
		}
		start = (start+len(size_byte))%size
		//  block   
		n =copy(r.buf[start:],b)
		if start+len(b) > len(r.buf){
			copy(r.buf,b[n:])//        
		}
		start = (start+block_size)%size
		//  ringbuffer    
		r.use = (start+size-r.start)%size
		return true
	}
	return false
}//       
func (r *Ringbuffer) Write(b []byte) bool {
	block_size:=len(b)
	if block_size > 0 {
		size:=len(r.buf)
		start:=(r.start+r.use)%size
		size_byte:= IntToByte(block_size)
		//  ringbuffer        block
		end:=(start+len(b)+len(size_byte))
		flag:=end-len(r.buf)
		if flag>0 && flag > r.start {
			return false
		}	
		//  block   
		n:=copy(r.buf[start:],size_byte)
		if start+len(size_byte) > len(r.buf){
			copy(r.buf,size_byte[n:])
		}
		start = (start+len(size_byte))%size
		//  block   
		n =copy(r.buf[start:],b)
		if start+len(b) > len(r.buf){
			copy(r.buf,b[n:])
		}
		start = (start+block_size)%size
		//  ringbuffer    
		r.use = (start+size-r.start)%size
		return true
	}
	return false
}
func (r *Ringbuffer) Read(b []byte) int{
	if r.use > 0 {//          
		//  block   
		size_byte:=make([]byte,4)
		t:=copy(size_byte,r.buf[r.start:])
		if t!=4 {//         
		   copy(size_byte[t:4],r.buf[:])
		}
		rblock_size:= ByteToInt(size_byte)
		//  block   
		start:=(r.start+4)%len(r.buf)
		nread:=0
		if start+rblock_size >= len(r.buf) {
		     n:= copy(b,r.buf[start:])//             
		     nread = copy(b[n:],r.buf[:])
		     nread = nread + n
		}else{
		    nread = copy(b,r.buf[start:start+rblock_size])
		}	
		if nread == rblock_size {
		     r.start = (r.start + rblock_size + 4)%len(r.buf)
		     r.use = r.use - rblock_size - 4
		     return nread
		}else{
			return -1
		}
	}
	return 0
}
func (r *Ringbuffer) GetUse() int{
	return r.use
}

좋은 웹페이지 즐겨찾기