366 lines
7.1 KiB
Go
366 lines
7.1 KiB
Go
package internal
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"quantex.com/qfixdpl/quickfix/datadictionary"
|
|
)
|
|
|
|
func isDecimalType(quickfixType string) bool {
|
|
switch quickfixType {
|
|
case "FIXDecimal", "FIXUDecimal":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func checkIfDecimalImportRequiredForFields(fTypes []*datadictionary.FieldType) (ok bool, err error) {
|
|
var t string
|
|
for _, fType := range fTypes {
|
|
t, err = quickfixType(fType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if isDecimalType(t) {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkIfTimeImportRequiredForFields(fTypes []*datadictionary.FieldType) (ok bool, err error) {
|
|
var t string
|
|
for _, fType := range fTypes {
|
|
t, err = quickfixType(fType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var vt string
|
|
if vt, err = quickfixValueType(t); err != nil {
|
|
return
|
|
}
|
|
|
|
if vt == "time.Time" {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkFieldDecimalRequired(f *datadictionary.FieldDef) (required bool, err error) {
|
|
var globalType *datadictionary.FieldType
|
|
if globalType, err = getGlobalFieldType(f); err != nil {
|
|
return
|
|
}
|
|
|
|
var t string
|
|
if t, err = quickfixType(globalType); err != nil {
|
|
return
|
|
}
|
|
|
|
if isDecimalType(t) {
|
|
required = true
|
|
return
|
|
}
|
|
|
|
for _, groupField := range f.Fields {
|
|
if required, err = checkFieldDecimalRequired(groupField); required || err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkFieldTimeRequired(f *datadictionary.FieldDef) (required bool, err error) {
|
|
var globalType *datadictionary.FieldType
|
|
if globalType, err = getGlobalFieldType(f); err != nil {
|
|
return
|
|
}
|
|
|
|
var t string
|
|
if t, err = quickfixType(globalType); err != nil {
|
|
return
|
|
}
|
|
|
|
var vt string
|
|
if vt, err = quickfixValueType(t); err != nil {
|
|
return
|
|
}
|
|
|
|
if vt == "time.Time" {
|
|
required = true
|
|
return
|
|
}
|
|
|
|
for _, groupField := range f.Fields {
|
|
if required, err = checkFieldTimeRequired(groupField); required || err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func collectStandardImports(m *datadictionary.MessageDef) (imports []string, err error) {
|
|
var timeRequired bool
|
|
for _, f := range m.Fields {
|
|
if !timeRequired {
|
|
if timeRequired, err = checkFieldTimeRequired(f); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
if timeRequired {
|
|
break
|
|
}
|
|
}
|
|
|
|
if timeRequired {
|
|
imports = append(imports, "time")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func collectExtraImports(m *datadictionary.MessageDef) (imports []string, err error) {
|
|
var decimalRequired bool
|
|
importPath := "github.com/shopspring/decimal"
|
|
if *useUDecimal {
|
|
importPath = "github.com/quagmt/udecimal"
|
|
}
|
|
for _, f := range m.Fields {
|
|
if !decimalRequired {
|
|
if decimalRequired, err = checkFieldDecimalRequired(f); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
if decimalRequired {
|
|
break
|
|
}
|
|
}
|
|
|
|
if decimalRequired {
|
|
imports = append(imports, importPath)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkIfEnumImportRequired(m *datadictionary.MessageDef) (required bool, err error) {
|
|
for _, f := range m.Fields {
|
|
required, err = checkFieldEnumRequired(f)
|
|
if err != nil || required {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func checkFieldEnumRequired(f *datadictionary.FieldDef) (required bool, err error) {
|
|
var globalType *datadictionary.FieldType
|
|
if globalType, err = getGlobalFieldType(f); err != nil {
|
|
return
|
|
}
|
|
|
|
if globalType.Enums != nil && 0 < len(globalType.Enums) {
|
|
var t string
|
|
if t, err = quickfixType(globalType); err != nil {
|
|
return
|
|
}
|
|
if t != "FIXBoolean" {
|
|
required = true
|
|
return
|
|
}
|
|
}
|
|
|
|
for _, groupField := range f.Fields {
|
|
if required, err = checkFieldEnumRequired(groupField); required || err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func quickfixValueType(quickfixType string) (goType string, err error) {
|
|
switch quickfixType {
|
|
case "FIXString":
|
|
goType = "string"
|
|
case "FIXBoolean":
|
|
goType = "bool"
|
|
case "FIXInt":
|
|
goType = "int"
|
|
case "FIXUTCTimestamp":
|
|
goType = "time.Time"
|
|
case "FIXFloat":
|
|
goType = "float64"
|
|
case "FIXDecimal":
|
|
goType = "decimal.Decimal"
|
|
case "FIXUDecimal":
|
|
goType = "udecimal.Decimal"
|
|
default:
|
|
err = fmt.Errorf("Unknown QuickFIX Type: %v", quickfixType)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func quickfixType(field *datadictionary.FieldType) (quickfixType string, err error) {
|
|
switch field.Type {
|
|
case "MULTIPLESTRINGVALUE", "MULTIPLEVALUESTRING":
|
|
fallthrough
|
|
case "MULTIPLECHARVALUE":
|
|
fallthrough
|
|
case "CHAR":
|
|
fallthrough
|
|
case "CURRENCY":
|
|
fallthrough
|
|
case "DATA":
|
|
fallthrough
|
|
case "MONTHYEAR":
|
|
fallthrough
|
|
case "LOCALMKTTIME", "LOCALMKTDATE":
|
|
fallthrough
|
|
case "TIME":
|
|
fallthrough
|
|
case "DATE":
|
|
fallthrough
|
|
case "EXCHANGE":
|
|
fallthrough
|
|
case "LANGUAGE":
|
|
fallthrough
|
|
case "XMLDATA":
|
|
fallthrough
|
|
case "COUNTRY":
|
|
fallthrough
|
|
case "UTCTIMEONLY":
|
|
fallthrough
|
|
case "UTCDATE":
|
|
fallthrough
|
|
case "UTCDATEONLY":
|
|
fallthrough
|
|
case "TZTIMEONLY":
|
|
fallthrough
|
|
case "TZTIMESTAMP":
|
|
fallthrough
|
|
case "XID", "XIDREF":
|
|
fallthrough
|
|
case "STRING":
|
|
quickfixType = "FIXString"
|
|
|
|
case "BOOLEAN":
|
|
quickfixType = "FIXBoolean"
|
|
|
|
case "LENGTH":
|
|
fallthrough
|
|
case "DAYOFMONTH":
|
|
fallthrough
|
|
case "NUMINGROUP":
|
|
fallthrough
|
|
case "SEQNUM":
|
|
fallthrough
|
|
case "TAGNUM":
|
|
fallthrough
|
|
case "INT":
|
|
quickfixType = "FIXInt"
|
|
|
|
case "UTCTIMESTAMP":
|
|
quickfixType = "FIXUTCTimestamp"
|
|
|
|
case "QTY":
|
|
fallthrough
|
|
case "QUANTITY":
|
|
fallthrough
|
|
case "AMT":
|
|
fallthrough
|
|
case "PRICE":
|
|
fallthrough
|
|
case "PRICEOFFSET":
|
|
fallthrough
|
|
case "PERCENTAGE":
|
|
fallthrough
|
|
case "FLOAT":
|
|
if *useFloat {
|
|
quickfixType = "FIXFloat"
|
|
} else if *useUDecimal {
|
|
quickfixType = "FIXUDecimal"
|
|
} else {
|
|
quickfixType = "FIXDecimal"
|
|
}
|
|
|
|
default:
|
|
err = fmt.Errorf("Unknown type '%v' for tag '%v'\n", field.Type, field.Tag())
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func requiredFields(m *datadictionary.MessageDef) (required []*datadictionary.FieldDef) {
|
|
for _, part := range m.RequiredParts() {
|
|
if part.Required() {
|
|
switch pType := part.(type) {
|
|
case *datadictionary.FieldDef:
|
|
if !pType.IsGroup() {
|
|
required = append(required, pType)
|
|
}
|
|
case *datadictionary.Component:
|
|
for _, f := range pType.RequiredFields() {
|
|
if !f.IsGroup() {
|
|
required = append(required, f)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func beginString(spec *datadictionary.DataDictionary) string {
|
|
if spec.FIXType == "FIXT" || spec.Major == 5 {
|
|
return "FIXT.1.1"
|
|
}
|
|
|
|
return fmt.Sprintf("FIX.%v.%v", spec.Major, spec.Minor)
|
|
}
|
|
|
|
func routerBeginString(spec *datadictionary.DataDictionary) (routerBeginString string) {
|
|
switch {
|
|
case spec.FIXType == "FIXT":
|
|
routerBeginString = "FIXT.1.1"
|
|
case spec.Major != 5 && spec.ServicePack == 0:
|
|
routerBeginString = fmt.Sprintf("FIX.%v.%v", spec.Major, spec.Minor)
|
|
// ApplVerID enums.
|
|
case spec.Major == 2:
|
|
routerBeginString = "0"
|
|
case spec.Major == 3:
|
|
routerBeginString = "1"
|
|
case spec.Major == 4 && spec.Minor == 0:
|
|
routerBeginString = "2"
|
|
case spec.Major == 4 && spec.Minor == 1:
|
|
routerBeginString = "3"
|
|
case spec.Major == 4 && spec.Minor == 2:
|
|
routerBeginString = "4"
|
|
case spec.Major == 4 && spec.Minor == 3:
|
|
routerBeginString = "5"
|
|
case spec.Major == 4 && spec.Minor == 4:
|
|
routerBeginString = "6"
|
|
case spec.Major == 5 && spec.Minor == 0 && spec.ServicePack == 0:
|
|
routerBeginString = "7"
|
|
case spec.Major == 5 && spec.Minor == 0 && spec.ServicePack == 1:
|
|
routerBeginString = "8"
|
|
case spec.Major == 5 && spec.Minor == 0 && spec.ServicePack == 2:
|
|
routerBeginString = "9"
|
|
}
|
|
|
|
return
|
|
}
|