123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912 |
- #region Copyright
- ////////////////////////////////////////////////////////////////////////////////
- // The following FIT Protocol software provided may be used with FIT protocol
- // devices only and remains the copyrighted property of Dynastream Innovations Inc.
- // The software is being provided on an "as-is" basis and as an accommodation,
- // and therefore all warranties, representations, or guarantees of any kind
- // (whether express, implied or statutory) including, without limitation,
- // warranties of merchantability, non-infringement, or fitness for a particular
- // purpose, are specifically disclaimed.
- //
- // Copyright 2016 Dynastream Innovations Inc.
- ////////////////////////////////////////////////////////////////////////////////
- // ****WARNING**** This file is auto-generated! Do NOT edit this file.
- // Profile Version = 16.60Release
- // Tag = production-akw-16.60.00-0-g5d3d436
- ////////////////////////////////////////////////////////////////////////////////
- #endregion
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using System.IO;
- using Dynastream.Utility;
- namespace Dynastream.Fit
- {
- /// <summary>
- ///
- /// </summary>
- public class Mesg
- {
- #region Fields
- protected byte localNum = 0;
- protected uint systemTimeOffset = 0;
- public List<Field> fields = new List<Field>();
- #endregion
- #region Properties
- public string Name { get; set; }
- public ushort Num { get; set; }
- public byte LocalNum
- {
- get
- {
- return localNum;
- }
- set
- {
- if (value > Fit.LocalMesgNumMask)
- {
- throw new FitException("Mesg:LocalNum - Invalid Local message number " + value + ". Local message number must be < " + Fit.LocalMesgNumMask);
- }
- else
- {
- localNum = value;
- }
- }
- }
- #endregion
- #region Constructors
- public Mesg(Mesg mesg)
- {
- if (mesg == null)
- {
- this.Name = "unknown";
- this.Num = (ushort)MesgNum.Invalid;
- return;
- }
- this.Name = mesg.Name;
- this.Num = mesg.Num;
- this.LocalNum = mesg.LocalNum;
- this.systemTimeOffset = mesg.systemTimeOffset;
- foreach (Field field in mesg.fields)
- {
- if (field.GetNumValues() > 0)
- {
- this.fields.Add(new Field(field));
- }
- }
- }
- public Mesg(string name, ushort num)
- {
- this.Name = name;
- this.Num = num;
- }
- internal Mesg(ushort mesgNum)
- : this(Profile.GetMesg(mesgNum))
- {
- }
- public Mesg(Stream fitStream, MesgDefinition defnMesg)
- : this(defnMesg.GlobalMesgNum)
- {
- Read(fitStream, defnMesg);
- }
- #endregion
- #region Methods
- public void Read(Stream inStream, MesgDefinition defnMesg)
- {
- inStream.Position = 1;
- EndianBinaryReader mesgReader = new EndianBinaryReader(inStream, defnMesg.IsBigEndian);
- LocalNum = defnMesg.LocalMesgNum;
- foreach (FieldDefinition fieldDef in defnMesg.GetFields())
- {
- // It's possible the field type found in the field definition may
- // not agree with the type defined in the profile. The profile
- // type will be preferred for decode.
- Field field = GetField(fieldDef.Num);
- if (field == null)
- {
- // We normally won't have fields attached to our skeleton message,
- // as we add values we need to add the fields too based on the mesg,field
- // combo in the profile. Must derive from the profile so the scale etc
- // is correct
- field = new Field(Profile.GetMesg(this.Num).GetField(fieldDef.Num));
- if (field.Num == Fit.FieldNumInvalid)
- {
- // If there was no info in the profile the FieldNum will get set to invalid
- // so preserve the unknown fields info while we know it
- field.Num = fieldDef.Num;
- field.Type = fieldDef.Type;
- }
- SetField(field);
- }
- object value;
- // strings may be an array and are of variable length
- if ((field.Type & Fit.BaseTypeNumMask) == Fit.String)
- {
- List<byte> utf8Bytes = new List<byte>();
- byte b = new byte();
- for (int i = 0; i < fieldDef.Size; i++)
- {
- b = mesgReader.ReadByte();
- if (b == 0x00)
- {
- field.AddValue(utf8Bytes.ToArray());
- utf8Bytes.Clear();
- }
- else
- {
- utf8Bytes.Add(b);
- }
- }
- if (utf8Bytes.Count != 0)
- {
- field.AddValue(utf8Bytes.ToArray());
- utf8Bytes.Clear();
- }
- }
- else
- {
- int numElements = (int)fieldDef.Size / Fit.BaseType[field.Type & Fit.BaseTypeNumMask].size;
- for (int i = 0; i < numElements; i++)
- {
- bool invalid = true;
- switch (field.Type & Fit.BaseTypeNumMask)
- {
- case Fit.Enum:
- case Fit.Byte:
- case Fit.UInt8:
- case Fit.UInt8z:
- value = mesgReader.ReadByte();
- if ((byte)value != (byte)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.SInt8:
- value = mesgReader.ReadSByte();
- if ((sbyte)value != (sbyte)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.SInt16:
- value = mesgReader.ReadInt16();
- if ((short)value != (short)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.UInt16:
- case Fit.UInt16z:
- value = mesgReader.ReadUInt16();
- if ((ushort)value != (ushort)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.SInt32:
- value = mesgReader.ReadInt32();
- if ((int)value != (int)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.UInt32:
- case Fit.UInt32z:
- value = mesgReader.ReadUInt32();
- if ((uint)value != (uint)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue)
- invalid = false;
- break;
- case Fit.Float32:
- value = mesgReader.ReadSingle();
- // TODO! Unless we find a different way to store floats, we dont have a good way to compare
- if (!float.IsNaN((float)value))
- invalid = false;
- break;
- case Fit.Float64:
- value = mesgReader.ReadDouble();
- // TODO! Unless we find a different way to store floats, we dont have a good way to compare
- if (!double.IsNaN((double)value))
- invalid = false;
- break;
- default:
- value = mesgReader.ReadBytes(fieldDef.Size);
- break;
- }
- if (!invalid || numElements > 1)
- field.SetRawValue(i, value);
- }
- }
- }
- }
- public void Write(Stream outStream)
- {
- Write(outStream, null);
- }
- public void Write(Stream outStream, MesgDefinition mesgDef)
- {
- if (mesgDef == null)
- {
- mesgDef = new MesgDefinition(this);
- }
- EndianBinaryWriter bw = new EndianBinaryWriter(outStream, mesgDef.IsBigEndian);
- bw.Write(LocalNum);
- foreach (FieldDefinition fieldDef in mesgDef.GetFields())
- {
- Field field = GetField(fieldDef.Num);
- if (null == field)
- {
- field = Profile.GetField(this.Num, fieldDef.Num);
- if( null != field )
- {
- fields.Add(field);
- }
- else
- {
- //Field does not exist in profile, continue to next field
- continue;
- }
- }
- // The field could be blank, correctly formed or partially filled
- while (field.GetSize() < fieldDef.Size)
- {
- if ((field.GetNumValues() == 1) && ((fieldDef.Type & Fit.BaseTypeNumMask) == Fit.String))
- {
- //Has to be a string.
- try
- {
- byte[] value = (byte[])field.GetValue();
- List<byte> temp = new List<byte>(value);
- while (temp.Count < fieldDef.Size)
- temp.Add(Convert.ToByte(Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue));
- field.SetValue(temp.ToArray());
- }
- catch (Exception) { throw new FitException("Exception occurred while resizing field to match definition."); }
- }
- else
- {
- field.AddValue(Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue);
- }
- }
- for (int i = 0; i < field.GetNumValues(); i++)
- {
- object value = field.GetRawValue(i);
- if (value == null)
- {
- value = Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue;
- }
- switch (fieldDef.Type & Fit.BaseTypeNumMask)
- {
- case Fit.Enum:
- case Fit.Byte:
- case Fit.UInt8:
- case Fit.UInt8z:
- bw.Write((byte)value);
- break;
- case Fit.SInt8:
- bw.Write((sbyte)value);
- break;
- case Fit.SInt16:
- bw.Write((short)value);
- break;
- case Fit.UInt16:
- case Fit.UInt16z:
- bw.Write((ushort)value);
- break;
- case Fit.SInt32:
- bw.Write((int)value);
- break;
- case Fit.UInt32:
- case Fit.UInt32z:
- bw.Write((uint)value);
- break;
- case Fit.Float32:
- bw.Write((float)value);
- break;
- case Fit.Float64:
- bw.Write((double)value);
- break;
- case Fit.String:
- bw.Write((byte[])value);
- // Write the null terminator
- bw.Write((byte)0x00);
- break;
- default:
- break;
- }
- }
- }
- }
- #region FieldList Manipulation Functions
- public bool HasField(byte fieldNum)
- {
- foreach (Field field in fields)
- {
- if (field.Num == fieldNum)
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// Replace an existing field, otherwise add a reference to fields list
- /// </summary>
- /// <param name="field">Caller allocated field</param>
- public void SetField(Field field)
- {
- for (int i = 0; i < fields.Count; i++)
- {
- if (fields[i].Num == field.Num)
- {
- fields[i] = field;
- return;
- }
- }
- fields.Add(field);
- }
- /// <summary>
- /// Insert a field at the desired index. If the field already exists in the mesg it is first removed.
- /// </summary>
- /// <param name="index">Index to insert the field, if index is out of range, the field is added to the end of the list</param>
- /// <param name="field">Caller allocated field</param>
- public void InsertField(int index, Field field)
- {
- // if message already contains this field, remove it
- for (int i = 0; i < fields.Count; i++)
- {
- if (fields[i].Num == field.Num)
- {
- fields.RemoveAt(i);
- }
- }
- // if the index is out of range, add to the end
- if (index < 0 || index > fields.Count)
- {
- fields.Add(field);
- }
- // insert the new field at desired index
- else
- {
- fields.Insert(index, field);
- }
- }
- public void SetFields(Mesg mesg)
- {
- if (mesg.Num != Num)
- {
- return;
- }
- foreach (Field field in mesg.fields)
- {
- SetField(new Field(field));
- }
- }
- public int GetNumFields()
- {
- return fields.Count;
- }
- public Field GetField(byte fieldNum)
- {
- foreach (Field field in fields)
- {
- if (field.Num == fieldNum)
- {
- return field;
- }
- }
- return null;
- }
- public Field GetField(string fieldName)
- {
- return GetField(fieldName, true);
- }
- public Field GetField(string fieldName, bool checkMesgSupportForSubFields)
- {
- foreach (Field field in fields)
- {
- if (field.Name == fieldName)
- {
- return field;
- }
- foreach (Subfield subfield in field.subfields)
- {
- if ((subfield.Name == fieldName) && (!checkMesgSupportForSubFields || (subfield.CanMesgSupport(this))))
- {
- return field;
- }
- }
- }
- return null;
- }
- public ushort GetActiveSubFieldIndex(byte fieldNum)
- {
- Field testField = new Field(this.GetField(fieldNum));
- if (testField == null)
- {
- return Fit.SubfieldIndexMainField;
- }
- for (ushort i = 0; i < testField.subfields.Count; i++)
- {
- if (testField.subfields[i].CanMesgSupport(this))
- {
- return i;
- }
- }
- return Fit.SubfieldIndexMainField;
- }
- public string GetActiveSubFieldName(byte fieldNum)
- {
- Field testField = new Field(this.GetField(fieldNum));
- if (testField == null)
- {
- return Fit.SubfieldNameMainField;
- }
- foreach (Subfield subfield in testField.subfields)
- {
- if (subfield.CanMesgSupport(this))
- {
- return subfield.Name;
- }
- }
- return Fit.SubfieldNameMainField;
- }
- #endregion
- public int GetNumFieldValues(byte fieldNum)
- {
- Field field = GetField(fieldNum);
- if (field != null)
- {
- return field.GetNumValues();
- }
- return 0;
- }
- public int GetNumFieldValues(String fieldName)
- {
- Field field = GetField(fieldName);
- if (field != null)
- {
- return field.GetNumValues();
- }
- return 0;
- }
- public int GetNumFieldValues(byte fieldNum, ushort subfieldIndex)
- {
- Field field = GetField(fieldNum);
- if (field == null)
- {
- return 0;
- }
- if (subfieldIndex == Fit.SubfieldIndexActiveSubfield)
- {
- return field.GetNumValues();
- }
- Subfield subfield = field.GetSubfield(subfieldIndex);
- if ((subfield == null) || (subfield.CanMesgSupport(this)))
- {
- return field.GetNumValues();
- }
- else
- {
- return 0;
- }
- }
- public int GetNumFieldValues(byte fieldNum, string subfieldName)
- {
- Field field = GetField(fieldNum);
- if (field == null)
- {
- return 0;
- }
- Subfield subfield = field.GetSubfield(subfieldName);
- if ((subfield == null) || (subfield.CanMesgSupport(this)))
- {
- return field.GetNumValues();
- }
- else
- {
- return 0;
- }
- }
- public object GetFieldValue(byte fieldNum)
- {
- return GetFieldValue(fieldNum, 0, Fit.SubfieldIndexActiveSubfield);
- }
- public object GetFieldValue(byte fieldNum, int fieldArrayIndex)
- {
- return GetFieldValue(fieldNum, fieldArrayIndex, Fit.SubfieldIndexActiveSubfield);
- }
- public object GetFieldValue(byte fieldNum, int fieldArrayIndex, ushort subFieldIndex)
- {
- Field field = GetField(fieldNum);
- if (field == null)
- {
- return null;
- }
- if (subFieldIndex == Fit.SubfieldIndexActiveSubfield)
- {
- return field.GetValue(fieldArrayIndex, GetActiveSubFieldIndex(fieldNum));
- }
- else
- {
- Subfield subfield = field.GetSubfield(subFieldIndex);
- if ((subfield == null) || (subfield.CanMesgSupport(this)))
- {
- return field.GetValue(fieldArrayIndex, subFieldIndex);
- }
- else
- {
- return null;
- }
- }
- }
- public object GetFieldValue(byte fieldNum, int fieldArrayIndex, string subfieldName)
- {
- Field field = GetField(fieldNum);
- if (field == null)
- {
- return null;
- }
- Subfield subfield = field.GetSubfield(subfieldName);
- if ((subfield == null) || (subfield.CanMesgSupport(this)))
- {
- return field.GetValue(fieldArrayIndex, subfieldName);
- }
- else
- {
- return null;
- }
- }
- public object GetFieldValue(string name)
- {
- return GetFieldValue(name, 0);
- }
- public object GetFieldValue(string name, int fieldArrayIndex)
- {
- Field field = GetField(name, false);
- if (field == null)
- {
- return null;
- }
- Subfield subfield = field.GetSubfield(name);
- if ((subfield == null) || (subfield.CanMesgSupport(this)))
- {
- return field.GetValue(fieldArrayIndex, name);
- }
- else
- {
- return null;
- }
- }
- public bool GetIsFieldAccumulated(byte num)
- {
- Field field = GetField(num);
- if (field != null)
- {
- return field.IsAccumulated;
- }
- return false;
- }
- public void SetFieldValue(byte fieldNum, Object value)
- {
- SetFieldValue(fieldNum, 0, value, Fit.SubfieldIndexActiveSubfield);
- }
- public void SetFieldValue(byte fieldNum, int fieldArrayIndex, Object value)
- {
- SetFieldValue(fieldNum, fieldArrayIndex, value, Fit.SubfieldIndexActiveSubfield);
- }
- public void SetFieldValue(byte fieldNum, int fieldArrayIndex, Object value, ushort subfieldIndex)
- {
- if (subfieldIndex == Fit.SubfieldIndexActiveSubfield)
- {
- subfieldIndex = GetActiveSubFieldIndex(fieldNum);
- }
- else
- {
- Field testField = new Field(this.GetField(fieldNum));
- Subfield subfield = testField.GetSubfield(subfieldIndex);
- if ((subfield != null) && !(subfield.CanMesgSupport(this)))
- {
- return;
- }
- }
- Field field = GetField(fieldNum);
- if (field == null)
- {
- // We normally won't have fields attached to our skeleton message,
- // as we add values we need to add the fields too based on the mesg,field
- // combo in the profile.
- field = new Field(Profile.GetMesg(this.Num).GetField(fieldNum));
- if (field.Num == Fit.FieldNumInvalid)
- {
- // If there was no info in the profile our FieldNum will get set to invalid,
- // at least preserve FieldNum while we know it
- field.Num = fieldNum;
- }
- SetField(field);
- }
- field.SetValue(fieldArrayIndex, value, subfieldIndex);
- }
- public void SetFieldValue(byte fieldNum, int fieldArrayIndex, Object value, String subfieldName)
- {
- Field testField = new Field(this.GetField(fieldNum));
- Subfield subfield = testField.GetSubfield(subfieldName);
- if ((subfield != null) && !(subfield.CanMesgSupport(this)))
- {
- return;
- }
- Field field = GetField(fieldNum);
- if (field == null)
- {
- // We normally won't have fields attached to our skeleton message,
- // as we add values we need to add the fields too based on the mesg,field
- // combo in the profile.
- field = new Field(Profile.GetMesg(this.Num).GetField(fieldNum));
- if (field.Num == Fit.FieldNumInvalid)
- {
- // If there was no info in the profile our FieldNum will get set to invalid,
- // at least preserve FieldNum while we know it
- field.Num = fieldNum;
- }
- SetField(field);
- }
- field.SetValue(fieldArrayIndex, value, subfieldName);
- }
- public void SetFieldValue(String name, Object value)
- {
- SetFieldValue(name, 0, value);
- }
- public void SetFieldValue(String name, int fieldArrayIndex, Object value)
- {
- Field testField = new Field(this.GetField(name));
- Subfield subfield = testField.GetSubfield(name);
- if ((subfield != null) && !(subfield.CanMesgSupport(this)))
- {
- return;
- }
- Field field = GetField(name, false);
- if (field == null)
- {
- field = new Field(Profile.GetMesg(this.Num).GetField(name));
- SetField(field);
- }
- field.SetValue(fieldArrayIndex, value, name);
- }
- public DateTime TimestampToDateTime(uint timestamp)
- {
- DateTime dateTime = new DateTime(timestamp);
- dateTime.ConvertSystemTimeToUTC(systemTimeOffset);
- return dateTime;
- }
- public DateTime TimestampToDateTime(uint? timestamp)
- {
- DateTime dateTime = null;
- if (timestamp != null)
- {
- dateTime = new DateTime(timestamp ?? 0);
- dateTime.ConvertSystemTimeToUTC(systemTimeOffset);
- }
- return dateTime;
- }
- 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.GetMesg(this.Num).GetField(fC.fieldNum));
- //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.Num, fC.fieldNum, bitsValue.Value, fC.bits);
- }
- if (newField.IsNumeric())
- {
- double fbitsValue = Convert.ToDouble(bitsValue);
- fbitsValue = ((double)fbitsValue / fC.scale) - fC.offset;
- if (true == this.HasField(newField.Num))
- {
- f.SetValue(f.values.Count, 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 (true == this.HasField(newField.Num))
- {
- f.SetValue(f.values.Count, nonNumericBitsValue);
- }
- else
- {
- newField.SetValue(nonNumericBitsValue);
- }
- }
- offset += fC.bits;
- //Return each field as we iterate
- yield return new FieldComponentExpansion(newField, offset);
- }
- }
- }
- }
- public void ExpandComponents()
- {
- ExpandComponents(null);
- }
- public void ExpandComponents(Accumulator accumulator)
- {
- // Traverse the field list
- // Change to for loop so we can add items as we iterate
- for (int i = 0; i < fields.Count; ++i)
- {
- List<FieldComponent> componentList = null;
- // Determine the active subfield
- ushort activeSubfield = GetActiveSubFieldIndex(fields[i].Num);
- if (activeSubfield == Fit.SubfieldIndexMainField)
- {
- componentList = fields[i].components;
- }
- else
- {
- componentList = fields[i].GetSubfield(activeSubfield).Components;
- }
- // Traverse the component list
- int offset = 0;
- foreach (FieldComponentExpansion f in ExpandComponentsInList(componentList, fields[i], offset, accumulator))
- {
- //Add the new field
- fields.Add(f.GetField());
- //update offset
- offset = f.GetOffset();
- }
- }
- }
- #endregion
- }
- internal class FieldComponentExpansion
- {
- private int offset;
- private Field field;
- public FieldComponentExpansion(Field f, int offset)
- {
- field = f;
- this.offset = offset;
- }
- public int GetOffset()
- {
- return offset;
- }
- public Field GetField()
- {
- return field;
- }
- }
- } // namespace
|