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
70 changes: 43 additions & 27 deletions field_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,30 @@ import (
"time"
)

//tagValues stores a slice of TagValues
type tagValues struct {
//field stores a slice of TagValues
type field struct {
tvs []TagValue
}

func (f *tagValues) Tag() Tag {
func (f *field) Tag() Tag {
return f.tvs[0].tag
}

func (f *field) init(tag Tag, value []byte) {
if len(f.tvs) == 0 {
f.tvs = make([]TagValue, 1)
} else {
f.tvs = f.tvs[:1]
}
f.tvs[0].init(tag, value)
}

func (f *field) write(buffer *bytes.Buffer) {
for _, tv := range f.tvs {
buffer.Write(tv.bytes)
}
}

// tagOrder true if tag i should occur before tag j
type tagOrder func(i, j Tag) bool

Expand All @@ -29,7 +44,7 @@ func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) }

//FieldMap is a collection of fix fields that make up a fix message.
type FieldMap struct {
tagLookup map[Tag]*tagValues
tagLookup map[Tag]*field
tagSort
}

Expand All @@ -41,7 +56,7 @@ func (m *FieldMap) init() {
}

func (m *FieldMap) initWithOrdering(ordering tagOrder) {
m.tagLookup = make(map[Tag]*tagValues)
m.tagLookup = make(map[Tag]*field)
m.compare = ordering
}

Expand All @@ -68,12 +83,12 @@ func (m FieldMap) Has(tag Tag) bool {

//GetField parses of a field with Tag tag. Returned reject may indicate the field is not present, or the field value is invalid.
func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError {
tagValues, ok := m.tagLookup[tag]
f, ok := m.tagLookup[tag]
if !ok {
return ConditionallyRequiredFieldMissing(tag)
}

if err := parser.Read(tagValues.tvs[0].value); err != nil {
if err := parser.Read(f.tvs[0].value); err != nil {
return IncorrectDataFormatForValue(tag)
}

Expand All @@ -82,12 +97,12 @@ func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError

//GetBytes is a zero-copy GetField wrapper for []bytes fields
func (m FieldMap) GetBytes(tag Tag) ([]byte, MessageRejectError) {
tagValues, ok := m.tagLookup[tag]
f, ok := m.tagLookup[tag]
if !ok {
return nil, ConditionallyRequiredFieldMissing(tag)
}

return tagValues.tvs[0].value, nil
return f.tvs[0].value, nil
}

//GetBool is a GetField wrapper for bool fields
Expand Down Expand Up @@ -140,12 +155,12 @@ func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) {

//GetGroup is a Get function specific to Group Fields.
func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError {
tagValues, ok := m.tagLookup[parser.Tag()]
f, ok := m.tagLookup[parser.Tag()]
if !ok {
return ConditionallyRequiredFieldMissing(parser.Tag())
}

if _, err := parser.Read(tagValues.tvs); err != nil {
if _, err := parser.Read(f.tvs); err != nil {
if msgRejErr, ok := err.(MessageRejectError); ok {
return msgRejErr
}
Expand All @@ -157,9 +172,13 @@ func (m FieldMap) GetGroup(parser FieldGroupReader) MessageRejectError {

//SetField sets the field with Tag tag
func (m *FieldMap) SetField(tag Tag, field FieldValueWriter) *FieldMap {
tValues := m.getOrCreate(tag)
tValues.tvs = make([]TagValue, 1)
tValues.tvs[0].init(tag, field.Write())
return m.SetBytes(tag, field.Write())
}

//SetBytes sets bytes
func (m *FieldMap) SetBytes(tag Tag, value []byte) *FieldMap {
f := m.getOrCreate(tag)
f.init(tag, value)
return m
}

Expand All @@ -170,12 +189,13 @@ func (m *FieldMap) SetBool(tag Tag, value bool) *FieldMap {

//SetInt is a SetField wrapper for int fields
func (m *FieldMap) SetInt(tag Tag, value int) *FieldMap {
return m.SetField(tag, FIXInt(value))
v := FIXInt(value)
return m.SetBytes(tag, v.Write())
}

//SetString is a SetField wrapper for string fields
func (m *FieldMap) SetString(tag Tag, value string) *FieldMap {
return m.SetField(tag, FIXString(value))
return m.SetBytes(tag, []byte(value))
}

//Clear purges all fields from field map
Expand All @@ -186,31 +206,29 @@ func (m *FieldMap) Clear() {
}
}

func (m *FieldMap) add(f *tagValues) {
func (m *FieldMap) add(f *field) {
if _, ok := m.tagLookup[f.Tag()]; !ok {
m.tags = append(m.tags, f.Tag())
}

m.tagLookup[f.Tag()] = f
}

func (m *FieldMap) getOrCreate(tag Tag) *tagValues {
func (m *FieldMap) getOrCreate(tag Tag) *field {
if f, ok := m.tagLookup[tag]; ok {
return f
}

f := new(tagValues)
f := new(field)
m.tagLookup[tag] = f
m.tags = append(m.tags, tag)
return f
}

//Set is a setter for fields
func (m *FieldMap) Set(field FieldWriter) *FieldMap {
tValues := m.getOrCreate(field.Tag())
tValues.tvs = make([]TagValue, 1)
tValues.tvs[0].init(field.Tag(), field.Write())
m.tagLookup[field.Tag()] = tValues
f := m.getOrCreate(field.Tag())
f.init(field.Tag(), field.Write())
return m
}

Expand All @@ -228,10 +246,8 @@ func (m *FieldMap) sortedTags() []Tag {

func (m FieldMap) write(buffer *bytes.Buffer) {
for _, tag := range m.sortedTags() {
if fields, ok := m.tagLookup[tag]; ok {
for _, tv := range fields.tvs {
buffer.Write(tv.bytes)
}
if f, ok := m.tagLookup[tag]; ok {
f.write(buffer)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion fix_int.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ func (f *FIXInt) Read(bytes []byte) error {
}

func (f FIXInt) Write() []byte {
return []byte(strconv.Itoa(int(f)))
return strconv.AppendInt(nil, int64(f), 10)
}
20 changes: 10 additions & 10 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,23 @@ func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) {
return
}

msg.Header.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Header.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
fieldIndex++

parsedFieldBytes := &msg.fields[fieldIndex]
if rawBytes, err = extractSpecificField(parsedFieldBytes, tagBodyLength, rawBytes); err != nil {
return
}

msg.Header.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Header.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
fieldIndex++

parsedFieldBytes = &msg.fields[fieldIndex]
if rawBytes, err = extractSpecificField(parsedFieldBytes, tagMsgType, rawBytes); err != nil {
return
}

msg.Header.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Header.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
fieldIndex++

trailerBytes := []byte{}
Expand All @@ -174,13 +174,13 @@ func ParseMessage(msg *Message, rawMessage *bytes.Buffer) (err error) {

switch {
case parsedFieldBytes.tag.IsHeader():
msg.Header.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Header.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
case parsedFieldBytes.tag.IsTrailer():
msg.Trailer.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Trailer.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
default:
foundBody = true
trailerBytes = rawBytes
msg.Body.add(&tagValues{msg.fields[fieldIndex : fieldIndex+1]})
msg.Body.add(&field{msg.fields[fieldIndex : fieldIndex+1]})
}
if parsedFieldBytes.tag == tagCheckSum {
break
Expand Down Expand Up @@ -305,8 +305,8 @@ func (m *Message) String() string {
return string(m.build())
}

func newCheckSum(value int) FIXString {
return FIXString(fmt.Sprintf("%03d", value))
func formatCheckSum(value int) string {
return fmt.Sprintf("%03d", value)
}

//Build constructs a []byte from a Message instance
Expand All @@ -322,7 +322,7 @@ func (m *Message) build() []byte {

func (m *Message) cook() {
bodyLength := m.Header.length() + m.Body.length() + m.Trailer.length()
m.Header.SetField(tagBodyLength, FIXInt(bodyLength))
m.Header.SetInt(tagBodyLength, bodyLength)
checkSum := (m.Header.total() + m.Body.total() + m.Trailer.total()) % 256
m.Trailer.SetField(tagCheckSum, newCheckSum(checkSum))
m.Trailer.SetString(tagCheckSum, formatCheckSum(checkSum))
}
8 changes: 4 additions & 4 deletions repeating_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,24 +182,24 @@ func (f *RepeatingGroup) Read(tv []TagValue) ([]TagValue, error) {
group := new(Group)
group.initWithOrdering(tagOrdering)
for len(tv) > 0 {
field, ok := f.findItemInGroupTemplate(tv[0].tag)
gi, ok := f.findItemInGroupTemplate(tv[0].tag)
if !ok {
break
}

tvRange := tv
if tv, err = field.Read(tv); err != nil {
if tv, err = gi.Read(tv); err != nil {
return tv, err
}

if f.isDelimiter(field.Tag()) {
if f.isDelimiter(gi.Tag()) {
group = new(Group)
group.initWithOrdering(tagOrdering)

f.groups = append(f.groups, group)
}

group.tagLookup[tvRange[0].tag] = &tagValues{tvRange}
group.tagLookup[tvRange[0].tag] = &field{tvRange}
}

if len(f.groups) != expectedGroupSize {
Expand Down
21 changes: 10 additions & 11 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,21 @@ func (s *session) insertSendingTime(msg *Message) {
}
}

func optionallySetID(header Header, field Tag, value string) {
func optionallySetID(msg *Message, field Tag, value string) {
if len(value) != 0 {
header.SetString(field, value)
msg.Header.SetString(field, value)
}
}

func (s *session) fillDefaultHeader(msg *Message, inReplyTo *Message) {
msg.Header.SetField(tagBeginString, FIXString(s.sessionID.BeginString))

msg.Header.SetField(tagSenderCompID, FIXString(s.sessionID.SenderCompID))
optionallySetID(msg.Header, tagSenderSubID, s.sessionID.SenderSubID)
optionallySetID(msg.Header, tagSenderLocationID, s.sessionID.SenderLocationID)

msg.Header.SetField(tagTargetCompID, FIXString(s.sessionID.TargetCompID))
optionallySetID(msg.Header, tagTargetSubID, s.sessionID.TargetSubID)
optionallySetID(msg.Header, tagTargetLocationID, s.sessionID.TargetLocationID)
msg.Header.SetString(tagBeginString, s.sessionID.BeginString)
msg.Header.SetString(tagSenderCompID, s.sessionID.SenderCompID)
optionallySetID(msg, tagSenderSubID, s.sessionID.SenderSubID)
optionallySetID(msg, tagSenderLocationID, s.sessionID.SenderLocationID)

msg.Header.SetString(tagTargetCompID, s.sessionID.TargetCompID)
optionallySetID(msg, tagTargetSubID, s.sessionID.TargetSubID)
optionallySetID(msg, tagTargetLocationID, s.sessionID.TargetLocationID)

s.insertSendingTime(msg)

Expand Down
15 changes: 7 additions & 8 deletions tag_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ type TagValue struct {
}

func (tv *TagValue) init(tag Tag, value []byte) {
var buf bytes.Buffer
buf.WriteString(strconv.Itoa(int(tag)))
buf.WriteString("=")
buf.Write(value)
buf.WriteString("")
tv.bytes = strconv.AppendInt(nil, int64(tag), 10)
tv.bytes = append(tv.bytes, []byte("=")...)
tv.bytes = append(tv.bytes, value...)
tv.bytes = append(tv.bytes, []byte("")...)

tv.tag = tag
tv.bytes = buf.Bytes()
tv.value = value
}

Expand All @@ -41,8 +39,9 @@ func (tv *TagValue) parse(rawFieldBytes []byte) (err error) {
}

tv.tag = Tag(parsedTag)
tv.value = rawFieldBytes[(sepIndex + 1):(len(rawFieldBytes) - 1)]
tv.bytes = rawFieldBytes
n := len(rawFieldBytes)
tv.value = rawFieldBytes[(sepIndex + 1):(n - 1):(n - 1)]
tv.bytes = rawFieldBytes[:n:n]

return
}
Expand Down