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
14 changes: 7 additions & 7 deletions field_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

//FieldMap is a collection of fix fields that make up a fix message.
type FieldMap struct {
tagLookup map[Tag][]TagValue
tagLookup map[Tag][]tagValue
tagOrder
}

Expand Down Expand Up @@ -68,7 +68,7 @@ func trailerFieldOrder(i, j Tag) bool {
}

func (m *FieldMap) init(ordering tagOrder) {
m.tagLookup = make(map[Tag][]TagValue)
m.tagLookup = make(map[Tag][]tagValue)
m.tagOrder = ordering
}

Expand Down Expand Up @@ -109,34 +109,34 @@ func (m FieldMap) GetGroup(parser *RepeatingGroup) MessageRejectError {
return ConditionallyRequiredFieldMissing(parser.Tag)
}

if _, err := parser.Read(tagValues); err != nil {
if _, err := parser.read(tagValues); err != nil {
return incorrectDataFormatForValue(parser.Tag)
}

return nil
}

func (m FieldMap) SetField(tag Tag, field FieldValueWriter) FieldMap {
tValues := make([]TagValue, 1)
tValues := make([]tagValue, 1)
tValues[0].init(tag, field.Write())
m.tagLookup[tag] = tValues
return m
}

//Clear purges all fields from field map
func (m *FieldMap) Clear() {
m.tagLookup = make(map[Tag][]TagValue)
m.tagLookup = make(map[Tag][]tagValue)
}

func (m FieldMap) Set(field FieldWriter) FieldMap {
tValues := make([]TagValue, 1)
tValues := make([]tagValue, 1)
tValues[0].init(field.Tag(), field.Write())
m.tagLookup[field.Tag()] = tValues
return m
}

func (m FieldMap) SetGroup(field RepeatingGroup) FieldMap {
m.tagLookup[field.Tag] = field.TagValues()
m.tagLookup[field.Tag] = field.tagValues()
return m
}

Expand Down
11 changes: 7 additions & 4 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ type Message struct {
bodyBytes []byte

//field bytes as they appear in the raw message
fields []TagValue
fields []tagValue
}

//Message marshals itself
func (m Message) Marshal() Message { return m }

//parseError is returned when bytes cannot be parsed as a FIX message.
type parseError struct {
OrigError string
Expand Down Expand Up @@ -57,7 +60,7 @@ func parseMessage(rawMessage []byte) (Message, error) {
fieldCount++
}
}
msg.fields = make([]TagValue, fieldCount)
msg.fields = make([]tagValue, fieldCount)

fieldIndex := 0
var err error
Expand Down Expand Up @@ -177,7 +180,7 @@ func (m Message) reverseRoute() Message {
return reverseMsg
}

func extractSpecificField(field *TagValue, expectedTag Tag, buffer []byte) (remBuffer []byte, err error) {
func extractSpecificField(field *tagValue, expectedTag Tag, buffer []byte) (remBuffer []byte, err error) {
remBuffer, err = extractField(field, buffer)
switch {
case err != nil:
Expand All @@ -190,7 +193,7 @@ func extractSpecificField(field *TagValue, expectedTag Tag, buffer []byte) (remB
return
}

func extractField(parsedFieldBytes *TagValue, buffer []byte) (remBytes []byte, err error) {
func extractField(parsedFieldBytes *tagValue, buffer []byte) (remBytes []byte, err error) {
endIndex := bytes.IndexByte(buffer, '\001')
if endIndex == -1 {
err = parseError{OrigError: "extractField: No Trailing Delim in " + string(buffer)}
Expand Down
13 changes: 10 additions & 3 deletions registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import (
"fmt"
)

//Send determines the session to send msgBuilder using header fields BeginString, TargetCompID, SenderCompID
func Send(msg Message) (err error) {
//Marshaler Marshals self to quickfix.Message type
type Marshaler interface {
Marshal() Message
}

//Send determines the session to send Marshaler using header fields BeginString, TargetCompID, SenderCompID
func Send(m Marshaler) (err error) {
msg := m.Marshal()
var beginString FIXString
if err := msg.Header.GetField(tagBeginString, &beginString); err != nil {
return err
Expand All @@ -27,7 +33,8 @@ func Send(msg Message) (err error) {
return SendToTarget(msg, sessionID)
}

func SendToTarget(msg Message, sessionID SessionID) error {
func SendToTarget(m Marshaler, sessionID SessionID) error {
msg := m.Marshal()
session, err := LookupSession(sessionID)
if err != nil {
return err
Expand Down
20 changes: 10 additions & 10 deletions repeating_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ type GroupItem interface {
//Tag returns the tag identifying this GroupItem
Tag() Tag

//Parameter to Read is TagValues. For most fields, only the first TagValue will be required.
//The length of the slice extends from the TagValue mapped to the field to be read through the
//Parameter to Read is tagValues. For most fields, only the first tagValue will be required.
//The length of the slice extends from the tagValue mapped to the field to be read through the
//following fields. This can be useful for GroupItems made up of repeating groups.
//
//The Read function returns the remaining TagValues not processed by the GroupItem. If there was a
//The Read function returns the remaining tagValues not processed by the GroupItem. If there was a
//problem reading the field, an error may be returned
Read(TagValues) (TagValues, error)
read(tagValues) (tagValues, error)
}

type protoGroupElement struct {
tag Tag
}

func (t protoGroupElement) Tag() Tag { return t.tag }
func (t protoGroupElement) Read(tv TagValues) (TagValues, error) {
func (t protoGroupElement) read(tv tagValues) (tagValues, error) {
if tv[0].Tag == t.tag {
return tv[1:], nil
}
Expand Down Expand Up @@ -59,10 +59,10 @@ func (f *RepeatingGroup) Add() Group {
return g
}

//TagValues returns TagValues for all Items in the repeating group ordered by
//tagValues returns tagValues for all Items in the repeating group ordered by
//Group sequence and Group template order
func (f RepeatingGroup) TagValues() TagValues {
tvs := make(TagValues, 1, 1)
func (f RepeatingGroup) tagValues() tagValues {
tvs := make(tagValues, 1, 1)
tvs[0].init(f.Tag, []byte(strconv.Itoa(len(f.Groups))))

for _, group := range f.Groups {
Expand Down Expand Up @@ -116,7 +116,7 @@ func (f RepeatingGroup) isDelimiter(t Tag) bool {
return t == f.GroupTemplate[0].Tag()
}

func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
func (f *RepeatingGroup) read(tv tagValues) (tagValues, error) {
expectedGroupSize, err := atoi(tv[0].Value)
if err != nil {
return tv, err
Expand All @@ -137,7 +137,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
}

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

Expand Down
92 changes: 46 additions & 46 deletions repeating_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestRepeatingGroup_TagValues(t *testing.T) {

for _, test := range tests {
tvbytes := []byte{}
for _, tv := range test.f.TagValues() {
for _, tv := range test.f.tagValues() {
tvbytes = append(tvbytes, tv.bytes...)
}

Expand All @@ -89,26 +89,26 @@ func TestRepeatingGroup_TagValues(t *testing.T) {
func TestRepeatingGroup_ReadError(t *testing.T) {
singleFieldTemplate := GroupTemplate{GroupElement(1)}
tests := []struct {
tv TagValues
tv tagValues
expectedGroupNum int
}{
{
TagValues{
TagValue{Value: []byte("1")},
TagValue{Tag: Tag(2), Value: []byte("not in template")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
tagValues{
tagValue{Value: []byte("1")},
tagValue{Tag: Tag(2), Value: []byte("not in template")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
}, 0},
{
TagValues{
TagValue{Value: []byte("2")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
TagValue{Tag: Tag(2), Value: []byte("not in template")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
tagValues{
tagValue{Value: []byte("2")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
tagValue{Tag: Tag(2), Value: []byte("not in template")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
}, 1}}

for _, s := range tests {
f := RepeatingGroup{GroupTemplate: singleFieldTemplate}
_, err := f.Read(s.tv)
_, err := f.read(s.tv)
if err == nil || len(f.Groups) != s.expectedGroupNum {
t.Errorf("Should have raised an error because expected group number is wrong: %v instead of %v", len(f.Groups), s.expectedGroupNum)
}
Expand All @@ -122,55 +122,55 @@ func TestRepeatingGroup_Read(t *testing.T) {

tests := []struct {
groupTemplate GroupTemplate
tv TagValues
expectedGroupTvs []TagValues
tv tagValues
expectedGroupTvs []tagValues
}{
{singleFieldTemplate, TagValues{TagValue{Value: []byte("0")}},
[]TagValues{}},
{singleFieldTemplate, TagValues{TagValue{Value: []byte("1")}, TagValue{Tag: Tag(1), Value: []byte("hello")}},
[]TagValues{TagValues{TagValue{Tag: Tag(1), Value: []byte("hello")}}}},
{singleFieldTemplate, tagValues{tagValue{Value: []byte("0")}},
[]tagValues{}},
{singleFieldTemplate, tagValues{tagValue{Value: []byte("1")}, tagValue{Tag: Tag(1), Value: []byte("hello")}},
[]tagValues{tagValues{tagValue{Tag: Tag(1), Value: []byte("hello")}}}},
{singleFieldTemplate,
TagValues{TagValue{Value: []byte("1")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
TagValue{Tag: Tag(2), Value: []byte("not in group")}},
[]TagValues{
TagValues{TagValue{Tag: Tag(1), Value: []byte("hello")}}}},
tagValues{tagValue{Value: []byte("1")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
tagValue{Tag: Tag(2), Value: []byte("not in group")}},
[]tagValues{
tagValues{tagValue{Tag: Tag(1), Value: []byte("hello")}}}},
{singleFieldTemplate,
TagValues{TagValue{Value: []byte("2")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
TagValue{Tag: Tag(1), Value: []byte("world")}},
[]TagValues{
TagValues{TagValue{Tag: Tag(1), Value: []byte("hello")}},
TagValues{TagValue{Tag: Tag(1), Value: []byte("world")}},
tagValues{tagValue{Value: []byte("2")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
tagValue{Tag: Tag(1), Value: []byte("world")}},
[]tagValues{
tagValues{tagValue{Tag: Tag(1), Value: []byte("hello")}},
tagValues{tagValue{Tag: Tag(1), Value: []byte("world")}},
}},
{multiFieldTemplate,
TagValues{
TagValue{Value: []byte("2")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
TagValue{Tag: Tag(1), Value: []byte("goodbye")}, TagValue{Tag: Tag(2), Value: []byte("cruel")}, TagValue{Tag: Tag(3), Value: []byte("world")},
tagValues{
tagValue{Value: []byte("2")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
tagValue{Tag: Tag(1), Value: []byte("goodbye")}, tagValue{Tag: Tag(2), Value: []byte("cruel")}, tagValue{Tag: Tag(3), Value: []byte("world")},
},
[]TagValues{
TagValues{TagValue{Tag: Tag(1), Value: []byte("hello")}},
TagValues{TagValue{Tag: Tag(1), Value: []byte("goodbye")}, TagValue{Tag: Tag(2), Value: []byte("cruel")}, TagValue{Tag: Tag(3), Value: []byte("world")}},
[]tagValues{
tagValues{tagValue{Tag: Tag(1), Value: []byte("hello")}},
tagValues{tagValue{Tag: Tag(1), Value: []byte("goodbye")}, tagValue{Tag: Tag(2), Value: []byte("cruel")}, tagValue{Tag: Tag(3), Value: []byte("world")}},
}},
{multiFieldTemplate,
TagValues{
TagValue{Value: []byte("3")},
TagValue{Tag: Tag(1), Value: []byte("hello")},
TagValue{Tag: Tag(1), Value: []byte("goodbye")}, TagValue{Tag: Tag(2), Value: []byte("cruel")}, TagValue{Tag: Tag(3), Value: []byte("world")},
TagValue{Tag: Tag(1), Value: []byte("another")},
tagValues{
tagValue{Value: []byte("3")},
tagValue{Tag: Tag(1), Value: []byte("hello")},
tagValue{Tag: Tag(1), Value: []byte("goodbye")}, tagValue{Tag: Tag(2), Value: []byte("cruel")}, tagValue{Tag: Tag(3), Value: []byte("world")},
tagValue{Tag: Tag(1), Value: []byte("another")},
},
[]TagValues{
TagValues{TagValue{Tag: Tag(1), Value: []byte("hello")}},
TagValues{TagValue{Tag: Tag(1), Value: []byte("goodbye")}, TagValue{Tag: Tag(2), Value: []byte("cruel")}, TagValue{Tag: Tag(3), Value: []byte("world")}},
TagValues{TagValue{Tag: Tag(1), Value: []byte("another")}},
[]tagValues{
tagValues{tagValue{Tag: Tag(1), Value: []byte("hello")}},
tagValues{tagValue{Tag: Tag(1), Value: []byte("goodbye")}, tagValue{Tag: Tag(2), Value: []byte("cruel")}, tagValue{Tag: Tag(3), Value: []byte("world")}},
tagValues{tagValue{Tag: Tag(1), Value: []byte("another")}},
}},
}

for _, test := range tests {
f := RepeatingGroup{GroupTemplate: test.groupTemplate}

_, err := f.Read(test.tv)
_, err := f.read(test.tv)
if err != nil {
t.Error(err)
}
Expand Down
22 changes: 11 additions & 11 deletions tag_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import (
"strconv"
)

//TagValue is a low-level FIX field abstraction
type TagValue struct {
//tagValue is a low-level FIX field abstraction
type tagValue struct {
Tag
Value []byte
bytes []byte
}

//TagValues is a slice of TagValue
type TagValues []TagValue
//tagValues is a slice of tagValue
type tagValues []tagValue

func (tv *TagValue) init(tag Tag, value []byte) {
func (tv *tagValue) init(tag Tag, value []byte) {
var buf bytes.Buffer
buf.WriteString(strconv.Itoa(int(tag)))
buf.WriteString("=")
Expand All @@ -28,18 +28,18 @@ func (tv *TagValue) init(tag Tag, value []byte) {
tv.Value = value
}

func (tv *TagValue) parse(rawFieldBytes []byte) (err error) {
func (tv *tagValue) parse(rawFieldBytes []byte) (err error) {
sepIndex := bytes.IndexByte(rawFieldBytes, '=')

if sepIndex == -1 {
err = fmt.Errorf("TagValue.Parse: No '=' in '%s'", rawFieldBytes)
err = fmt.Errorf("tagValue.Parse: No '=' in '%s'", rawFieldBytes)
return
}

parsedTag, err := atoi(rawFieldBytes[:sepIndex])

if err != nil {
err = fmt.Errorf("TagValue.Parse: %s", err.Error())
err = fmt.Errorf("tagValue.Parse: %s", err.Error())
return
}

Expand All @@ -50,11 +50,11 @@ func (tv *TagValue) parse(rawFieldBytes []byte) (err error) {
return
}

func (tv TagValue) String() string {
func (tv tagValue) String() string {
return string(tv.bytes)
}

func (tv TagValue) total() int {
func (tv tagValue) total() int {
total := 0

for _, b := range []byte(tv.bytes) {
Expand All @@ -64,6 +64,6 @@ func (tv TagValue) total() int {
return total
}

func (tv TagValue) length() int {
func (tv tagValue) length() int {
return len(tv.bytes)
}
Loading