diff --git a/aper.go b/aper.go index b45c46e..1838cb8 100644 --- a/aper.go +++ b/aper.go @@ -15,7 +15,11 @@ type perBitData struct { bitsOffset uint } -func perTrace(level int, s string) { +func perTrace(level int, format string, a ...interface{}) { + if !logger.IsLevelEnabledDebug() { + return + } + s := fmt.Sprintf(format, a...) _, file, line, ok := runtime.Caller(1) if !ok { logger.AperLog.Debugln(s) @@ -25,6 +29,9 @@ func perTrace(level int, s string) { } func perBitLog(numBits uint64, byteOffset uint64, bitsOffset uint, value interface{}) string { + if !logger.IsLevelEnabledDebug() { + return "" + } if reflect.TypeOf(value).Kind() == reflect.Uint64 { return fmt.Sprintf(" [PER got %2d bits, byteOffset(after): %d, bitsOffset(after): %d, value: 0x%0x]", numBits, byteOffset, bitsOffset, reflect.ValueOf(value).Uint()) @@ -130,7 +137,7 @@ func (pd *perBitData) getBitsValue(numBits uint) (value uint64, err error) { func (pd *perBitData) parseAlignBits() error { if (pd.bitsOffset & 0x7) > 0 { alignBits := 8 - ((pd.bitsOffset) & 0x7) - perTrace(2, fmt.Sprintf("Aligning %d bits", alignBits)) + perTrace(2, "Aligning %d bits", alignBits) if val, err := pd.getBitsValue(alignBits); err != nil { return err } else if val != 0 { @@ -148,7 +155,7 @@ func (pd *perBitData) parseAlignBits() error { } func (pd *perBitData) parseConstraintValue(valueRange int64) (value uint64, err error) { - perTrace(3, fmt.Sprintf("Getting Constraint Value with range %d", valueRange)) + perTrace(3, "Getting Constraint Value with range %d", valueRange) var bytes uint if valueRange <= 255 { @@ -269,7 +276,7 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB if sizeRange == 1 { sizes := uint64(ub+7) >> 3 bitString.BitLength = uint64(ub) - perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", ub)) + perTrace(2, "Decoding BIT STRING size %d", ub) if sizes > 2 { if err := pd.parseAlignBits(); err != nil { return bitString, err @@ -293,7 +300,7 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB bitString.Bytes = bytes } } - perTrace(2, fmt.Sprintf("Decoded BIT STRING (length = %d): %0.8b", ub, bitString.Bytes)) + perTrace(2, "Decoded BIT STRING (length = %d): %0.8b", ub, bitString.Bytes) return bitString, nil } repeat := false @@ -305,7 +312,7 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB rawLength = length } rawLength += uint64(lb) - perTrace(2, fmt.Sprintf("Decoding BIT STRING size %d", rawLength)) + perTrace(2, "Decoding BIT STRING size %d", rawLength) if rawLength == 0 { return bitString, nil } @@ -326,7 +333,7 @@ func (pd *perBitData) parseBitString(extensed bool, lowerBoundPtr *int64, upperB pd.byteOffset-- } perTrace(1, perBitLog(rawLength, pd.byteOffset, pd.bitsOffset, bitString.Bytes)) - perTrace(2, fmt.Sprintf("Decoded BIT STRING (length = %d): %0.8b", rawLength, bitString.Bytes)) + perTrace(2, "Decoded BIT STRING (length = %d): %0.8b", rawLength, bitString.Bytes) if !repeat { // if err = pd.parseAlignBits(); err != nil { @@ -358,7 +365,7 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe octetString := OctetString("") // lowerbound == upperbound if sizeRange == 1 { - perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", ub)) + perTrace(2, "Decoding OCTET STRING size %d", ub) if ub > 2 { unsignedUB := uint64(ub) if err := pd.parseAlignBits(); err != nil { @@ -378,7 +385,7 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe octetString = octet } } - perTrace(2, fmt.Sprintf("Decoded OCTET STRING (length = %d): 0x%0x", ub, octetString)) + perTrace(2, "Decoded OCTET STRING (length = %d): 0x%0x", ub, octetString) return octetString, nil } repeat := false @@ -390,7 +397,7 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe rawLength = length } rawLength += uint64(lb) - perTrace(2, fmt.Sprintf("Decoding OCTET STRING size %d", rawLength)) + perTrace(2, "Decoding OCTET STRING size %d", rawLength) if rawLength == 0 { return octetString, nil } else if err := pd.parseAlignBits(); err != nil { @@ -403,7 +410,7 @@ func (pd *perBitData) parseOctetString(extensed bool, lowerBoundPtr *int64, uppe octetString = append(octetString, pd.bytes[pd.byteOffset:pd.byteOffset+rawLength]...) pd.byteOffset += rawLength perTrace(1, perBitLog(8*rawLength, pd.byteOffset, pd.bitsOffset, octetString)) - perTrace(2, fmt.Sprintf("Decoded OCTET STRING (length = %d): 0x%0x", rawLength, octetString)) + perTrace(2, "Decoded OCTET STRING (length = %d): 0x%0x", rawLength, octetString) if !repeat { // if err = pd.parseAlignBits(); err != nil { // return @@ -442,9 +449,9 @@ func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBou if upperBoundPtr != nil { ub = *upperBoundPtr valueRange = ub - lb + 1 - perTrace(3, fmt.Sprintf("Decoding INTEGER with Value Range(%d..%d)", lb, ub)) + perTrace(3, "Decoding INTEGER with Value Range(%d..%d)", lb, ub) } else { - perTrace(3, fmt.Sprintf("Decoding INTEGER with Semi-Constraint Range(%d..)", lb)) + perTrace(3, "Decoding INTEGER with Semi-Constraint Range(%d..)", lb) } } } else { @@ -500,7 +507,7 @@ func (pd *perBitData) parseInteger(extensed bool, lowerBoundPtr *int64, upperBou return int64(0), err } } - perTrace(2, fmt.Sprintf("Decoding INTEGER Length with %d bytes", rawLength)) + perTrace(2, "Decoding INTEGER Length with %d bytes", rawLength) if rawValue, err := pd.getBitsValue(rawLength * 8); err != nil { return int64(0), err @@ -531,19 +538,19 @@ func (pd *perBitData) parseEnumerated(extensed bool, lowerBoundPtr *int64, upper } if extensed { - perTrace(2, fmt.Sprintf("Decoding ENUMERATED with Extensive Value of Range(%d..)", ub+1)) + perTrace(2, "Decoding ENUMERATED with Extensive Value of Range(%d..)", ub+1) if value, err = pd.parseNormallySmallNonNegativeWholeNumber(); err != nil { return } value += uint64(ub) + 1 } else { - perTrace(2, fmt.Sprintf("Decoding ENUMERATED with Value Range(%d..%d)", lb, ub)) + perTrace(2, "Decoding ENUMERATED with Value Range(%d..%d)", lb, ub) valueRange := ub - lb + 1 if valueRange > 1 { value, err = pd.parseConstraintValue(valueRange) } } - perTrace(2, fmt.Sprintf("Decoded ENUMERATED Value : %d", value)) + perTrace(2, "Decoded ENUMERATED Value : %d", value) return } @@ -559,10 +566,10 @@ func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, if !sizeExtensed && params.sizeUpperBound != nil && *params.sizeUpperBound < 65536 { ub := *params.sizeUpperBound sizeRange = ub - lb + 1 - perTrace(3, fmt.Sprintf("Decoding Length of \"SEQUENCE OF\" with Size Range(%d..%d)", lb, ub)) + perTrace(3, "Decoding Length of \"SEQUENCE OF\" with Size Range(%d..%d)", lb, ub) } else { sizeRange = -1 - perTrace(3, fmt.Sprintf("Decoding Length of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", lb)) + perTrace(3, "Decoding Length of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", lb) } var numElements uint64 @@ -587,7 +594,7 @@ func (pd *perBitData) parseSequenceOf(sizeExtensed bool, params fieldParameters, pd.byteOffset++ perTrace(1, perBitLog(8, pd.byteOffset, pd.bitsOffset, numElements)) } - perTrace(2, fmt.Sprintf("Decoding \"SEQUENCE OF\" struct %s with len(%d)", sliceType.Elem().Name(), numElements)) + perTrace(2, "Decoding \"SEQUENCE OF\" struct %s with len(%d)", sliceType.Elem().Name(), numElements) params.sizeExtensible = false params.sizeUpperBound = nil params.sizeLowerBound = nil @@ -612,7 +619,7 @@ func (pd *perBitData) getChoiceIndex(extensed bool, upperBoundPtr *int64) (prese } else if rawChoice, err1 := pd.parseConstraintValue(ub + 1); err1 != nil { err = err1 } else { - perTrace(2, fmt.Sprintf("Decoded Present index of CHOICE is %d + 1", rawChoice)) + perTrace(2, "Decoded Present index of CHOICE is %d + 1", rawChoice) present = int(rawChoice) + 1 } return @@ -671,12 +678,12 @@ func (pd *perBitData) parseOpenType(skip bool, v reflect.Value, params fieldPara } } if skip { - perTrace(2, fmt.Sprintf("Skip OpenType (len = %d byte)", len(pdOpenType.bytes))) + perTrace(2, "Skip OpenType (len = %d byte)", len(pdOpenType.bytes)) return nil } else { - perTrace(2, fmt.Sprintf("Decoding OpenType %s with (len = %d byte)", v.Type().String(), len(pdOpenType.bytes))) + perTrace(2, "Decoding OpenType %s with (len = %d byte)", v.Type().String(), len(pdOpenType.bytes)) err := parseField(v, pdOpenType, params) - perTrace(2, fmt.Sprintf("Decoded OpenType %s", v.Type().String())) + perTrace(2, "Decoded OpenType %s", v.Type().String()) return err } } @@ -704,7 +711,7 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { } else if bitsValue != 0 { sizeExtensible = true } - perTrace(2, fmt.Sprintf("Decoded Size Extensive Bit : %t", sizeExtensible)) + perTrace(2, "Decoded Size Extensive Bit : %t", sizeExtensible) } if params.valueExtensible && v.Kind() != reflect.Slice { if bitsValue, err1 := pd.getBitsValue(1); err1 != nil { @@ -712,7 +719,7 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { } else if bitsValue != 0 { valueExtensible = true } - perTrace(2, fmt.Sprintf("Decoded Value Extensive Bit : %t", valueExtensible)) + perTrace(2, "Decoded Value Extensive Bit : %t", valueExtensible) } // We deal with the structures defined in this package first. @@ -756,27 +763,25 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { return err } else { val.SetInt(parsedInt) - perTrace(2, fmt.Sprintf("Decoded INTEGER Value: %d", parsedInt)) + perTrace(2, "Decoded INTEGER Value: %d", parsedInt) return nil } case reflect.Struct: structType := fieldType - var structParams []fieldParameters + structField, err := structFieldCache.load(structType) + if err != nil { + return err + } var optionalCount uint var optionalPresents uint64 // pass tag for optional - for i := 0; i < structType.NumField(); i++ { - if structType.Field(i).PkgPath != "" { - return fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) - } - tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) + for i := 0; i < len(structField); i++ { // for optional flag - if tempParams.optional { + if structField[i].FieldParameters.optional { optionalCount++ } - structParams = append(structParams, tempParams) } if optionalCount > 0 { @@ -785,11 +790,11 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { } else { optionalPresents = optionalPresentsTmp } - perTrace(2, fmt.Sprintf("optionalPresents is %0b", optionalPresents)) + perTrace(2, "optionalPresents is %0b", optionalPresents) } // CHOICE or OpenType - if structType.NumField() > 0 && structType.Field(0).Name == "Present" { + if len(structField) > 0 && structField[0].FieldName == "Present" { var present int = 0 if params.openType { if params.referenceFieldValue == nil { @@ -797,11 +802,11 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { } refValue := *params.referenceFieldValue - for j, param := range structParams { + for j, param := range structField { if j == 0 { continue } - if param.referenceFieldValue != nil && *param.referenceFieldValue == refValue { + if param.FieldParameters.referenceFieldValue != nil && *param.FieldParameters.referenceFieldValue == refValue { present = j break } @@ -810,12 +815,12 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { val.Field(0).SetInt(0) perTrace(2, "OpenType reference value does not match any field") return pd.parseOpenType(true, reflect.Value{}, fieldParameters{}) - } else if present >= structType.NumField() { + } else if present >= len(structField) { return fmt.Errorf("OpenType Present is bigger than number of struct field") } else { val.Field(0).SetInt(int64(present)) - perTrace(2, fmt.Sprintf("Decoded Present index of OpenType is %d ", present)) - return pd.parseOpenType(false, val.Field(present), structParams[present]) + perTrace(2, "Decoded Present index of OpenType is %d ", present) + return pd.parseOpenType(false, val.Field(present), structField[present].FieldParameters) } } else { if presentTmp, err := pd.getChoiceIndex(valueExtensible, params.valueUpperBound); err != nil { @@ -826,44 +831,45 @@ func parseField(v reflect.Value, pd *perBitData, params fieldParameters) error { val.Field(0).SetInt(int64(present)) if present == 0 { return fmt.Errorf("CHOICE present is 0(present's field number)") - } else if present >= structType.NumField() { + } else if present >= len(structField) { return fmt.Errorf("CHOICE Present is bigger than number of struct field") } else { - return parseField(val.Field(present), pd, structParams[present]) + return parseField(val.Field(present), pd, structField[present].FieldParameters) } } } - for i := 0; i < structType.NumField(); i++ { - if structParams[i].optional && optionalCount > 0 { + for i := 0; i < len(structField); i++ { + if structField[i].FieldParameters.optional && optionalCount > 0 { optionalCount-- if optionalPresents&(1< 2 { pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes...) @@ -233,7 +238,7 @@ func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extens } else { err = pd.putBitString(bytes, uint(bitsLength)) } - perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", bitsLength, bytes)) + perTrace(2, "Encoded BIT STRING (length = %d): 0x%0x", bitsLength, bytes) return err } rawLength := bitsLength - uint64(lb) @@ -252,15 +257,15 @@ func (pd *perRawBitData) appendBitString(bytes []byte, bitsLength uint64, extens } partOfRawLength += uint64(lb) sizes := (partOfRawLength + 7) >> 3 - perTrace(2, fmt.Sprintf("Encoding BIT STRING size %d", partOfRawLength)) + perTrace(2, "Encoding BIT STRING size %d", partOfRawLength) if partOfRawLength == 0 { return err } pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+sizes]...) perTrace(1, perRawBitLog(partOfRawLength, len(pd.bytes), pd.bitsOffset, bytes)) - perTrace(2, fmt.Sprintf("Encoded BIT STRING (length = %d): 0x%0x", partOfRawLength, - bytes[byteOffset:byteOffset+sizes])) + perTrace(2, "Encoded BIT STRING (length = %d): 0x%0x", partOfRawLength, + bytes[byteOffset:byteOffset+sizes]) rawLength -= (partOfRawLength - uint64(lb)) if rawLength > 0 { byteOffset += sizes @@ -313,7 +318,7 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo err := fmt.Errorf("OctetString Length(%d) is not match fix-sized : %d", byteLen, ub) return err } - perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", ub)) + perTrace(2, "Encoding OCTET STRING size %d", ub) if byteLen > 2 { pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes...) @@ -322,7 +327,7 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo err := pd.putBitString(bytes, uint(byteLen*8)) return err } - perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", byteLen, bytes)) + perTrace(2, "Encoded OCTET STRING (length = %d): 0x%0x", byteLen, bytes) return nil } rawLength := byteLen - uint64(lb) @@ -340,15 +345,15 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo return err } partOfRawLength += uint64(lb) - perTrace(2, fmt.Sprintf("Encoding OCTET STRING size %d", partOfRawLength)) + perTrace(2, "Encoding OCTET STRING size %d", partOfRawLength) if partOfRawLength == 0 { return nil } pd.appendAlignBits() pd.bytes = append(pd.bytes, bytes[byteOffset:byteOffset+partOfRawLength]...) perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, bytes)) - perTrace(2, fmt.Sprintf("Encoded OCTET STRING (length = %d): 0x%0x", partOfRawLength, - bytes[byteOffset:byteOffset+partOfRawLength])) + perTrace(2, "Encoded OCTET STRING (length = %d): 0x%0x", partOfRawLength, + bytes[byteOffset:byteOffset+partOfRawLength]) rawLength -= (partOfRawLength - uint64(lb)) if rawLength > 0 { byteOffset += partOfRawLength @@ -362,7 +367,7 @@ func (pd *perRawBitData) appendOctetString(bytes []byte, extensive bool, lowerBo func (pd *perRawBitData) appendBool(value bool) error { var err error - perTrace(3, fmt.Sprintf("Encoding BOOLEAN Value %t", value)) + perTrace(3, "Encoding BOOLEAN Value %t", value) if value { err = pd.putBitsValue(1, 1) perTrace(2, "Encoded BOOLEAN Value : 0x1") @@ -396,14 +401,14 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt fmt.Printf("pd.putBitsValue(1, 1) error: %v", errTmp) } } else { - perTrace(3, fmt.Sprintf("Encoding INTEGER with Value Range(%d..%d)", lb, ub)) + perTrace(3, "Encoding INTEGER with Value Range(%d..%d)", lb, ub) if errTmp := pd.putBitsValue(0, 1); errTmp != nil { fmt.Printf("pd.putBitsValue(0, 1) error: %v", errTmp) } } } } else { - perTrace(3, fmt.Sprintf("Encoding INTEGER with Semi-Constraint Range(%d..)", lb)) + perTrace(3, "Encoding INTEGER with Semi-Constraint Range(%d..)", lb) } } else { perTrace(3, "Encoding INTEGER with Unconstraint Value") @@ -439,7 +444,7 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt // semi-constraint or unconstraint pd.appendAlignBits() pd.bytes = append(pd.bytes, byte(rawLength)) - perTrace(2, fmt.Sprintf("Encoding INTEGER Length %d in one byte", rawLength)) + perTrace(2, "Encoding INTEGER Length %d in one byte", rawLength) perTrace(1, perRawBitLog(8, len(pd.bytes), pd.bitsOffset, uint64(rawLength))) } else { @@ -460,12 +465,12 @@ func (pd *perRawBitData) appendInteger(value int64, extensive bool, lowerBoundPt break } } - perTrace(2, fmt.Sprintf("Encoding INTEGER Length %d-1 in %d bits", rawLength, i)) + perTrace(2, "Encoding INTEGER Length %d-1 in %d bits", rawLength, i) if err := pd.putBitsValue(uint64(rawLength-1), i); err != nil { return err } } - perTrace(2, fmt.Sprintf("Encoding INTEGER %d with %d bytes", value, rawLength)) + perTrace(2, "Encoding INTEGER %d with %d bytes", value, rawLength) rawLength *= 8 pd.appendAlignBits() @@ -497,7 +502,7 @@ func (pd *perRawBitData) appendEnumerated(value uint64, extensive bool, lowerBou } } valueRange := ub - lb + 1 - perTrace(2, fmt.Sprintf("Encoding ENUMERATED Value : %d with Value Range(%d..%d)", value, lb, ub)) + perTrace(2, "Encoding ENUMERATED Value : %d with Value Range(%d..%d)", value, lb, ub) if valueRange > 1 { return pd.appendConstraintValue(valueRange, value) } @@ -545,22 +550,22 @@ func (pd *perRawBitData) parseSequenceOf(v reflect.Value, params fieldParameters if numElements < lb { return fmt.Errorf("SEQUENCE OF Size is lower than lowerbound") } else if sizeRange == 1 { - perTrace(3, fmt.Sprintf("Encoding Length of \"SEQUENCE OF\" with fix-size %d", ub)) + perTrace(3, "Encoding Length of \"SEQUENCE OF\" with fix-size %d", ub) if numElements != ub { return fmt.Errorf("Encoding Length %d != fix-size %d", numElements, ub) } } else if sizeRange > 0 { - perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Size Range(%d..%d)", numElements, lb, ub)) + perTrace(3, "Encoding Length(%d) of \"SEQUENCE OF\" with Size Range(%d..%d)", numElements, lb, ub) if err := pd.appendConstraintValue(sizeRange, uint64(numElements-lb)); err != nil { return err } } else { - perTrace(3, fmt.Sprintf("Encoding Length(%d) of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", numElements, lb)) + perTrace(3, "Encoding Length(%d) of \"SEQUENCE OF\" with Semi-Constraint Range(%d..)", numElements, lb) pd.appendAlignBits() pd.bytes = append(pd.bytes, byte(numElements&0xff)) perTrace(1, perRawBitLog(8, len(pd.bytes), pd.bitsOffset, uint64(numElements))) } - perTrace(2, fmt.Sprintf("Encoding \"SEQUENCE OF\" struct %s with len(%d)", v.Type().Elem().Name(), numElements)) + perTrace(2, "Encoding \"SEQUENCE OF\" struct %s with len(%d)", v.Type().Elem().Name(), numElements) params.sizeExtensible = false params.sizeUpperBound = nil params.sizeLowerBound = nil @@ -582,7 +587,7 @@ func (pd *perRawBitData) appendChoiceIndex(present int, extensive bool, upperBou } else if extensive && rawChoice > int(ub) { return fmt.Errorf("Unsupport value of CHOICE type is in Extensed") } - perTrace(2, fmt.Sprintf("Encoding Present index of CHOICE %d - 1", present)) + perTrace(2, "Encoding Present index of CHOICE %d - 1", present) if err := pd.appendConstraintValue(ub+1, uint64(rawChoice)); err != nil { return err } @@ -591,14 +596,14 @@ func (pd *perRawBitData) appendChoiceIndex(present int, extensive bool, upperBou func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) error { pdOpenType := &perRawBitData{[]byte(""), 0} - perTrace(2, fmt.Sprintf("Encoding OpenType %s to temp RawData", v.Type().String())) + perTrace(2, "Encoding OpenType %s to temp RawData", v.Type().String()) if err := pdOpenType.makeField(v, params); err != nil { return err } openTypeBytes := pdOpenType.bytes rawLength := uint64(len(pdOpenType.bytes)) - perTrace(2, fmt.Sprintf("Encoding OpenType %s RawData : 0x%0x(%d bytes)", v.Type().String(), pdOpenType.bytes, - rawLength)) + perTrace(2, "Encoding OpenType %s RawData : 0x%0x(%d bytes)", v.Type().String(), pdOpenType.bytes, + rawLength) var byteOffset, partOfRawLength uint64 for { @@ -612,15 +617,15 @@ func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) if err := pd.appendLength(-1, partOfRawLength); err != nil { return err } - perTrace(2, fmt.Sprintf("Encoding Part of OpenType RawData size %d", partOfRawLength)) + perTrace(2, "Encoding Part of OpenType RawData size %d", partOfRawLength) if partOfRawLength == 0 { return nil } pd.appendAlignBits() pd.bytes = append(pd.bytes, openTypeBytes[byteOffset:byteOffset+partOfRawLength]...) perTrace(1, perRawBitLog(partOfRawLength*8, len(pd.bytes), pd.bitsOffset, openTypeBytes)) - perTrace(2, fmt.Sprintf("Encoded OpenType RawData (length = %d): 0x%0x", partOfRawLength, - openTypeBytes[byteOffset:byteOffset+partOfRawLength])) + perTrace(2, "Encoded OpenType RawData (length = %d): 0x%0x", partOfRawLength, + openTypeBytes[byteOffset:byteOffset+partOfRawLength]) rawLength -= partOfRawLength if rawLength > 0 { byteOffset += partOfRawLength @@ -630,7 +635,7 @@ func (pd *perRawBitData) appendOpenType(v reflect.Value, params fieldParameters) } } - perTrace(2, fmt.Sprintf("Encoded OpenType %s", v.Type().String())) + perTrace(2, "Encoded OpenType %s", v.Type().String()) return nil } @@ -674,27 +679,26 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) erro case reflect.Struct: structType := fieldType - var structParams []fieldParameters + structField, err := structFieldCache.load(structType) + if err != nil { + return err + } var optionalCount uint var optionalPresents uint64 var sequenceType bool // struct extensive TODO: support extensed type if params.valueExtensible { - perTrace(2, fmt.Sprintf("Encoding Value Extensive Bit : %t", false)) + perTrace(2, "Encoding Value Extensive Bit : %t", false) if err := pd.putBitsValue(0, 1); err != nil { return err } } - sequenceType = (structType.NumField() <= 0 || structType.Field(0).Name != "Present") + sequenceType = len(structField) <= 0 || structField[0].FieldName != "Present" // pass tag for optional - for i := 0; i < structType.NumField(); i++ { - if structType.Field(i).PkgPath != "" { - return fmt.Errorf("struct contains unexported fields : " + structType.Field(i).PkgPath) - } - tempParams := parseFieldParameters(structType.Field(i).Tag.Get("aper")) - if sequenceType { + if sequenceType { + for i := 0; i < len(structField); i++ { // for optional flag - if tempParams.optional { + if structField[i].FieldParameters.optional { optionalCount++ optionalPresents <<= 1 if !v.Field(i).IsNil() { @@ -704,11 +708,9 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) erro return fmt.Errorf("nil element in SEQUENCE type") } } - - structParams = append(structParams, tempParams) } if optionalCount > 0 { - perTrace(2, fmt.Sprintf("putting optional(%d), optionalPresents is %0b", optionalCount, optionalPresents)) + perTrace(2, "putting optional(%d), optionalPresents is %0b", optionalCount, optionalPresents) if err := pd.putBitsValue(optionalPresents, optionalCount); err != nil { return err } @@ -719,7 +721,7 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) erro present := int(v.Field(0).Int()) if present == 0 { return fmt.Errorf("CHOICE or OpenType present is 0(present's field number)") - } else if present >= structType.NumField() { + } else if present >= len(structField) { return fmt.Errorf("Present is bigger than number of struct field") } else if params.openType { if params.referenceFieldValue == nil { @@ -727,18 +729,19 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) erro } refValue := *params.referenceFieldValue - if structParams[present].referenceFieldValue == nil || *structParams[present].referenceFieldValue != refValue { + if structField[present].FieldParameters.referenceFieldValue == nil || + *structField[present].FieldParameters.referenceFieldValue != refValue { return fmt.Errorf("reference value and present reference value is not match") } - perTrace(2, fmt.Sprintf("Encoding Present index of OpenType is %d ", present)) - if err := pd.appendOpenType(val.Field(present), structParams[present]); err != nil { + perTrace(2, "Encoding Present index of OpenType is %d ", present) + if err := pd.appendOpenType(val.Field(present), structField[present].FieldParameters); err != nil { return err } } else { if err := pd.appendChoiceIndex(present, params.valueExtensible, params.valueUpperBound); err != nil { return err } - if err := pd.makeField(val.Field(present), structParams[present]); err != nil { + if err := pd.makeField(val.Field(present), structField[present].FieldParameters); err != nil { return err } } @@ -747,35 +750,36 @@ func (pd *perRawBitData) makeField(v reflect.Value, params fieldParameters) erro for i := 0; i < structType.NumField(); i++ { // optional - if structParams[i].optional && optionalCount > 0 { + if structField[i].FieldParameters.optional && optionalCount > 0 { optionalCount-- if optionalPresents&(1<