adding quickfix
This commit is contained in:
165
quickfix/parser.go
Normal file
165
quickfix/parser.go
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright (c) quickfixengine.org All rights reserved.
|
||||
//
|
||||
// This file may be distributed under the terms of the quickfixengine.org
|
||||
// license as defined by quickfixengine.org and appearing in the file
|
||||
// LICENSE included in the packaging of this file.
|
||||
//
|
||||
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
|
||||
// THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
|
||||
// PARTICULAR PURPOSE.
|
||||
//
|
||||
// See http://www.quickfixengine.org/LICENSE for licensing information.
|
||||
//
|
||||
// Contact ask@quickfixengine.org if any conditions of this licensing
|
||||
// are not clear to you.
|
||||
|
||||
package quickfix
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultBufSize = 4096
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
// Buffer is a slice of bigBuffer.
|
||||
bigBuffer, buffer []byte
|
||||
reader io.Reader
|
||||
lastRead time.Time
|
||||
}
|
||||
|
||||
func newParser(reader io.Reader) *parser {
|
||||
return &parser{reader: reader}
|
||||
}
|
||||
|
||||
func (p *parser) readMore() (int, error) {
|
||||
if len(p.buffer) == cap(p.buffer) {
|
||||
var newBuffer []byte
|
||||
switch {
|
||||
// Initialize the parser.
|
||||
case len(p.bigBuffer) == 0:
|
||||
p.bigBuffer = make([]byte, defaultBufSize)
|
||||
newBuffer = p.bigBuffer[0:0]
|
||||
|
||||
// Shift buffer back to the start of bigBuffer.
|
||||
case 2*len(p.buffer) <= len(p.bigBuffer):
|
||||
newBuffer = p.bigBuffer[0:len(p.buffer)]
|
||||
|
||||
// Reallocate big buffer with enough space to shift buffer.
|
||||
default:
|
||||
p.bigBuffer = make([]byte, 2*len(p.buffer))
|
||||
newBuffer = p.bigBuffer[0:len(p.buffer)]
|
||||
}
|
||||
|
||||
copy(newBuffer, p.buffer)
|
||||
p.buffer = newBuffer
|
||||
}
|
||||
|
||||
n, e := p.reader.Read(p.buffer[len(p.buffer):cap(p.buffer)])
|
||||
p.lastRead = time.Now()
|
||||
p.buffer = p.buffer[:len(p.buffer)+n]
|
||||
return n, e
|
||||
}
|
||||
|
||||
func (p *parser) findIndex(delim []byte) (int, error) {
|
||||
return p.findIndexAfterOffset(0, delim)
|
||||
}
|
||||
|
||||
func (p *parser) findIndexAfterOffset(offset int, delim []byte) (int, error) {
|
||||
for {
|
||||
if offset > len(p.buffer) {
|
||||
if n, err := p.readMore(); n == 0 && err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if index := bytes.Index(p.buffer[offset:], delim); index != -1 {
|
||||
return index + offset, nil
|
||||
}
|
||||
|
||||
n, err := p.readMore()
|
||||
|
||||
if n == 0 && err != nil {
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) findStart() (int, error) {
|
||||
return p.findIndex([]byte("8="))
|
||||
}
|
||||
|
||||
func (p *parser) findEndAfterOffset(offset int) (int, error) {
|
||||
index, err := p.findIndexAfterOffset(offset, []byte("\00110="))
|
||||
if err != nil {
|
||||
return index, err
|
||||
}
|
||||
|
||||
index, err = p.findIndexAfterOffset(index+1, []byte("\001"))
|
||||
if err != nil {
|
||||
return index, err
|
||||
}
|
||||
|
||||
return index + 1, nil
|
||||
}
|
||||
|
||||
func (p *parser) jumpLength() (int, error) {
|
||||
lengthIndex, err := p.findIndex([]byte("9="))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
lengthIndex += 3
|
||||
|
||||
offset, err := p.findIndexAfterOffset(lengthIndex, []byte("\001"))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if offset == lengthIndex {
|
||||
return 0, errors.New("No length given")
|
||||
}
|
||||
|
||||
length, err := atoi(p.buffer[lengthIndex:offset])
|
||||
if err != nil {
|
||||
return length, err
|
||||
}
|
||||
|
||||
if length <= 0 {
|
||||
return length, errors.New("Invalid length")
|
||||
}
|
||||
|
||||
return offset + length, nil
|
||||
}
|
||||
|
||||
func (p *parser) ReadMessage() (msgBytes *bytes.Buffer, err error) {
|
||||
start, err := p.findStart()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
p.buffer = p.buffer[start:]
|
||||
|
||||
index, err := p.jumpLength()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
index, err = p.findEndAfterOffset(index)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
msgBytes = new(bytes.Buffer)
|
||||
msgBytes.Reset()
|
||||
msgBytes.Write(p.buffer[:index])
|
||||
p.buffer = p.buffer[index:]
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user