Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 4 additions & 41 deletions field_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package quickfix

import (
"bytes"
"math"
"sort"
)

Expand All @@ -24,50 +23,14 @@ func (t tagSort) Len() int { return len(t.tags) }
func (t tagSort) Swap(i, j int) { t.tags[i], t.tags[j] = t.tags[j], t.tags[i] }
func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) }

//in the message header, the first 3 tags in the message header must be 8,9,35
func headerFieldOrder(i, j Tag) bool {
var ordering = func(t Tag) uint32 {
switch t {
case tagBeginString:
return 1
case tagBodyLength:
return 2
case tagMsgType:
return 3
}

return math.MaxUint32
}

orderi := ordering(i)
orderj := ordering(j)

switch {
case orderi < orderj:
return true
case orderi > orderj:
return false
}

return i < j
}

// In the body, ascending tags
// ascending tags
func normalFieldOrder(i, j Tag) bool { return i < j }

// In the trailer, CheckSum (tag 10) must be last
func trailerFieldOrder(i, j Tag) bool {
switch {
case i == tagCheckSum:
return false
case j == tagCheckSum:
return true
}

return i < j
func (m *FieldMap) init() {
m.initWithOrdering(normalFieldOrder)
}

func (m *FieldMap) init(ordering tagOrder) {
func (m *FieldMap) initWithOrdering(ordering tagOrder) {
m.tagLookup = make(map[Tag]TagValues)
m.tagOrder = ordering
}
Expand Down
16 changes: 8 additions & 8 deletions field_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
)

func TestFieldMap_Clear(t *testing.T) {
fMap := FieldMap{}
fMap.init(normalFieldOrder)
var fMap FieldMap
fMap.init()

fMap.SetField(1, FIXString("hello"))
fMap.SetField(2, FIXString("world"))
Expand All @@ -19,8 +19,8 @@ func TestFieldMap_Clear(t *testing.T) {
}

func TestFieldMap_SetAndGet(t *testing.T) {
fMap := FieldMap{}
fMap.init(normalFieldOrder)
var fMap FieldMap
fMap.init()

fMap.SetField(1, FIXString("hello"))
fMap.SetField(2, FIXString("world"))
Expand Down Expand Up @@ -57,8 +57,8 @@ func TestFieldMap_SetAndGet(t *testing.T) {
}

func TestFieldMap_Length(t *testing.T) {
fMap := FieldMap{}
fMap.init(normalFieldOrder)
var fMap FieldMap
fMap.init()
fMap.SetField(1, FIXString("hello"))
fMap.SetField(2, FIXString("world"))
fMap.SetField(8, FIXString("FIX.4.4"))
Expand All @@ -72,8 +72,8 @@ func TestFieldMap_Length(t *testing.T) {

func TestFieldMap_Total(t *testing.T) {

fMap := FieldMap{}
fMap.init(normalFieldOrder)
var fMap FieldMap
fMap.init()
fMap.SetField(1, FIXString("hello"))
fMap.SetField(2, FIXString("world"))
fMap.SetField(8, FIXString("FIX.4.4"))
Expand Down
6 changes: 3 additions & 3 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ func Marshal(v interface{}) Message {
}
continue
case "Header":
e.FieldMap = m.Header
e.FieldMap = m.Header.FieldMap
case "Trailer":
e.FieldMap = m.Trailer
e.FieldMap = m.Trailer.FieldMap
default:
e.FieldMap = m.Body
e.FieldMap = m.Body.FieldMap
}

e.encodeField(sf, sf.Type, reflectValue.Field(i))
Expand Down
8 changes: 4 additions & 4 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,10 @@ func TestMarshal_HeaderTrailer(t *testing.T) {
fixMsgPart quickfix.FieldMap
expected []byte
}{
{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header, []byte("0")},
{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header, []byte("hello")},
{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body, []byte("world")},
{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer, []byte("3")},
{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("0")},
{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("hello")},
{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body.FieldMap, []byte("world")},
{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer.FieldMap, []byte("3")},
}

for _, test := range tests {
Expand Down
79 changes: 68 additions & 11 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,77 @@ package quickfix
import (
"bytes"
"fmt"
"math"
"time"

"github.com/quickfixgo/quickfix/enum"
)

//Header is first section of a FIX Message
type Header struct{ FieldMap }

//Init initializes the Header instance
func (h *Header) Init() {
//in the message header, the first 3 tags in the message header must be 8,9,35
h.initWithOrdering(func(i, j Tag) bool {
var ordering = func(t Tag) uint32 {
switch t {
case tagBeginString:
return 1
case tagBodyLength:
return 2
case tagMsgType:
return 3
}

return math.MaxUint32
}

orderi := ordering(i)
orderj := ordering(j)

switch {
case orderi < orderj:
return true
case orderi > orderj:
return false
}

return i < j
})
}

//Body is the primary application section of a FIX message
type Body struct{ FieldMap }

//Init initializes the FIX message
func (b *Body) Init() {
b.init()
}

//Trailer is the last section of a FIX message
type Trailer struct{ FieldMap }

//Init initializes the FIX message
func (t *Trailer) Init() {
// In the trailer, CheckSum (tag 10) must be last
t.initWithOrdering(func(i, j Tag) bool {
switch {
case i == tagCheckSum:
return false
case j == tagCheckSum:
return true
}

return i < j
})
}

//Message is a FIX Message abstraction.
type Message struct {
Header FieldMap
Trailer FieldMap
Body FieldMap
Header Header
Trailer Trailer
Body Body

//ReceiveTime is the time that this message was read from the socket connection
ReceiveTime time.Time
Expand All @@ -38,15 +99,11 @@ func (e parseError) Error() string { return fmt.Sprintf("error parsing message:

//NewMessage returns a newly initialized Message instance
func NewMessage() (m Message) {
m.Init()
return
}
m.Header.Init()
m.Body.Init()
m.Trailer.Init()

//Init initializes the Message instance
func (m *Message) Init() {
m.Header.init(headerFieldOrder)
m.Body.init(normalFieldOrder)
m.Trailer.init(trailerFieldOrder)
return
}

//ParseMessage constructs a Message from a byte slice wrapping a FIX message.
Expand Down
6 changes: 3 additions & 3 deletions repeating_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (f RepeatingGroup) Get(i int) Group {
//Add appends a new group to the RepeatingGroup and returns the new Group
func (f *RepeatingGroup) Add() Group {
var g Group
g.init(f.groupTagOrder())
g.initWithOrdering(f.groupTagOrder())

f.groups = append(f.groups, g)
return g
Expand Down Expand Up @@ -157,7 +157,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
tv = tv[1:cap(tv)]
tagOrdering := f.groupTagOrder()
var group Group
group.init(tagOrdering)
group.initWithOrdering(tagOrdering)
for len(tv) > 0 {
field, ok := f.findItemInGroupTemplate(tv[0].tag)
if !ok {
Expand All @@ -171,7 +171,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {

if f.isDelimiter(field.Tag()) {
group = Group{}
group.init(tagOrdering)
group.initWithOrdering(tagOrdering)

f.groups = append(f.groups, group)
}
Expand Down
7 changes: 4 additions & 3 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package quickfix

import (
"fmt"
"sync"
"time"

"github.com/quickfixgo/quickfix/config"
"github.com/quickfixgo/quickfix/datadictionary"
"github.com/quickfixgo/quickfix/enum"
"sync"
"time"
)

//The Session is the primary FIX abstraction for message communication
Expand Down Expand Up @@ -152,7 +153,7 @@ func (s *session) onDisconnect() {
s.log.OnEvent("Disconnected")
}

func (s *session) insertSendingTime(header FieldMap) {
func (s *session) insertSendingTime(header Header) {
sendingTime := time.Now().UTC()

if s.sessionID.BeginString >= enum.BeginStringFIX42 {
Expand Down
6 changes: 3 additions & 3 deletions session_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package quickfix

import (
"github.com/quickfixgo/quickfix/enum"
"testing"
"time"

"github.com/quickfixgo/quickfix/enum"
)

func buildMessage() Message {
builder := Message{}
builder.Init()
builder := NewMessage()
builder.Header.SetField(tagBeginString, FIXString(enum.BeginStringFIX40))
builder.Header.SetField(tagMsgType, FIXString("D"))
return builder
Expand Down
6 changes: 3 additions & 3 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ func Unmarshal(m Message, v interface{}) MessageRejectError {
case "FIXMsgType":
continue
case "Header":
d.FieldMap = m.Header
d.FieldMap = m.Header.FieldMap
case "Trailer":
d.FieldMap = m.Trailer
d.FieldMap = m.Trailer.FieldMap
default:
d.FieldMap = m.Body
d.FieldMap = m.Body.FieldMap
}

if err := d.decodeField(sf, sf.Type, sv); err != nil {
Expand Down
6 changes: 3 additions & 3 deletions validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,15 @@ func validateOrder(msg Message) MessageRejectError {
}

func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message Message) MessageRejectError {
if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header); err != nil {
if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header.FieldMap); err != nil {
return err
}

if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body); err != nil {
if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body.FieldMap); err != nil {
return err
}

if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer); err != nil {
if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer.FieldMap); err != nil {
return err
}

Expand Down