private IEnumerable <FieldComponentExpansion> ExpandComponentsInList(List <FieldComponent> componentList, Field currentField, int offset, Accumulator accumulator) { // When components.Count > 0 a field will be created and appended to the field list if ((componentList != null) && (componentList.Count > 0)) { foreach (FieldComponent fC in componentList) { if (fC.fieldNum != Fit.FieldNumInvalid) { //Create a new field to expand into Field newField = new Field(Profile.GetMessage(this.MessageNumber).GetField(fC.fieldNum)); // Mark that this field has been generated through expansion newField.IsExpandedField = true; //cache a field that we use to set properties on Field f = this.GetField(newField.Num); // GetBitsValue will not return more bits than the componentField type can hold. // This means strings are built one letter at a time when using components // which is a bad idea to start with) long?bitsValue = currentField.GetBitsValue(offset, fC.bits, newField.Type); if (bitsValue == null) { break; } if (true == fC.accumulate) { bitsValue = accumulator.Accumulate(this.MessageNumber, fC.fieldNum, bitsValue.Value, fC.bits); } if (newField.IsNumeric()) { // If the field is invalid, set the raw value so that // the invalid value is not scaled or offset. if (FitBaseType.IsNumericInvalid((long)bitsValue, newField.GetType())) { if (this.HasField(newField.Num)) { f.SetRawValue(f.GetNumValues(), bitsValue); } else { newField.SetRawValue(0, bitsValue); } } else { double fbitsValue = Convert.ToDouble(bitsValue); fbitsValue = ((double)fbitsValue / fC.scale) - fC.offset; if (this.HasField(newField.Num)) { f.SetValue(f.GetNumValues(), fbitsValue); } else { newField.SetValue(fbitsValue); } } } // Shouldn't apply scale/offset to string or enum else { object nonNumericBitsValue; // Ensure strings are added as byte[] if ((newField.Type & Fit.BaseTypeNumMask) == Fit.String) { nonNumericBitsValue = new byte[] { (byte)bitsValue }; } else { nonNumericBitsValue = bitsValue; } if (HasField(newField.Num)) { f.SetValue(f.GetNumValues(), nonNumericBitsValue); } else { newField.SetValue(nonNumericBitsValue); } } offset += fC.bits; //Return each field as we iterate yield return(new FieldComponentExpansion(newField, offset)); } } } }
public void ExpandComponents() { // We can't modify the fields collection as we are traversing it, save new fields // to add after we complete expansion List <Field> newFields = new List <Field>(); foreach (Field myField in fields) { List <FieldComponent> compsToExpand = null; Field containingField = null; // Determine the active subfield and expand if it has any components ushort activeSubfield = GetActiveSubFieldIndex(myField.Num); if (activeSubfield == Fit.SubfieldIndexMainField) { // There are main field components, expand if (myField.components.Count > 0) { compsToExpand = myField.components; containingField = myField; } } else { // There are subfield components, expand if (myField.GetSubfield(activeSubfield).Components.Count > 0) { compsToExpand = myField.GetSubfield(activeSubfield).Components; containingField = myField; } } if (compsToExpand != null) { // Comp Decode if (containingField.values.Count > 0) { int offset = 0; foreach (FieldComponent component in compsToExpand) { if (component.fieldNum != Fit.FieldNumInvalid) { Field destinationField = new Field(Profile.GetMesg(this.Num).GetField(component.fieldNum)); // GetBitsValue will not return more bits than the componentField type can hold. // This means strings are built one letter at a time when using components // which is a bad idea to start with) long?bitsValue = containingField.GetBitsValue(offset, component.bits, destinationField.Type); if (bitsValue == null) { break; } if (component.accumulate == true) { bitsValue = component.Accumulate(bitsValue.Value); } if (destinationField.IsNumeric()) { float fbitsValue = Convert.ToSingle(bitsValue); fbitsValue = ((float)fbitsValue / component.scale) - component.offset; if (this.HasField(destinationField.Num) == true) { this.GetField(destinationField.Num).SetValue(this.GetField(destinationField.Num).values.Count, fbitsValue); } else { destinationField.SetValue(fbitsValue); newFields.Add(destinationField); } } // Shouldn't apply scale/offset to string or enum else { object nonNumericBitsValue; // Ensure strings are added as byte[] if ((destinationField.Type & Fit.BaseTypeNumMask) == Fit.String) { nonNumericBitsValue = new byte[] { (byte)bitsValue }; } else { nonNumericBitsValue = bitsValue; } if (this.HasField(destinationField.Num) == true) { this.GetField(destinationField.Num).SetValue(this.GetField(destinationField.Num).values.Count, nonNumericBitsValue); } else { destinationField.SetValue(nonNumericBitsValue); newFields.Add(destinationField); } } } offset += component.bits; } } } } foreach (Field newField in newFields) { // Another component added this field during expansion, append the additional values if (this.HasField(newField.Num) == true) { foreach (object newValue in newField.values) { this.GetField(newField.Num).SetValue(this.GetField(newField.Num).values.Count, newValue); } } // Add the new field else { this.SetField(newField); } } }