/// <summary> /// Resets all primitive fields in the container to valid values, recursively. /// (For the moment, we'll assume that's all that's required.) /// </summary> public void Reset(FixedContainer context, ModuleData data) { foreach (var field in Fields.OfType <IPrimitiveField>()) { field.Reset(context, data); } }
public override bool TrySetText(FixedContainer context, ModuleData data, string text) { var address = GetAddress(context); if (text.Length > Length || text.Any(c => c < 32 || c > 126)) { return(false); } text = text.PadRight(Length); switch (bytesPerChar) { case 1: byte[] ascii = Encoding.ASCII.GetBytes(text); data.SetData(address, ascii); break; case 2: byte[] rawBytes = new byte[Length * 2]; for (int i = 0; i < Length; i++) { rawBytes[i * 2] = (byte)(text[i] >> 4); rawBytes[i * 2 + 1] = (byte)(text[i] & 0xf); } data.SetData(address, rawBytes); break; default: throw new InvalidOperationException($"Can't set a string with bytesPerChar of {bytesPerChar}"); } return(true); }
public bool Validate(FixedContainer context, ModuleData data, out string?error) { var segment = data.GetSegment(GetAddress(context)); // TODO: Check the length against size? if (segment == null) { error = "No segment containing field present in the module data."; return(false); } return(ValidateData(context, data, out error)); }
public Container GetOverlaidContainer(FixedContainer context, ModuleData data) { var switchContainerAddress = context.Address + SwitchContainerOffset; var switchContainer = Schema.LoadableContainersByAddress[switchContainerAddress]; var switchContext = new FixedContainer(switchContainer, switchContainerAddress); var field = switchContainer.GetField(switchField); int index = field switch { // User samples get an extra overlay at the end. InstrumentField instrumentField => instrumentField.GetInstrument(switchContext, data).Group?.Index ?? Schema.InstrumentGroups.Count, NumericFieldBase nfb => nfb.GetRawValue(switchContext, data), _ => throw new InvalidOperationException($"Invalid switch field type '{field.GetType()}'") }; return(OverlaidContainers[index]); } }
public override string GetText(FixedContainer context, ModuleData data) { var address = GetAddress(context); byte[] rawBytes = data.GetData(address, Size); switch (bytesPerChar) { case 1: return(Encoding.ASCII.GetString(rawBytes)); case 2: byte[] asciiBytes = new byte[Length]; for (int i = 0; i < Length; i++) { asciiBytes[i] = (byte)((rawBytes[i * 2] << 4) | rawBytes[i * 2 + 1]); } return(Encoding.ASCII.GetString(asciiBytes)); default: throw new InvalidOperationException($"Can't get a string with bytesPerChar of {bytesPerChar}"); } }
/// <summary> /// Validates the data against the field. This is called by <see cref="Validate"/> /// after performing the common check that the field has a segment in the module data. /// Implementations may therefore assume that the data exists. /// </summary> protected abstract bool ValidateData(FixedContainer context, ModuleData data, [NotNullWhen(false)] out string?error);
public abstract bool TrySetText(FixedContainer context, ModuleData data, string text);
public abstract void Reset(FixedContainer context, ModuleData data);
public abstract string GetText(FixedContainer context, ModuleData data);
protected override bool ValidateData(FixedContainer context, ModuleData data, out string?error) { // We could potentially validate that it contains non-control-character ASCII... error = null; return(true); }
public override void Reset(FixedContainer context, ModuleData data) => TrySetText(context, data, new string(' ', Length));
public void SetValue(FixedContainer context, ModuleData data, bool value) => SetRawValue(context, data, value ? 1 : 0);
public bool GetValue(FixedContainer context, ModuleData data) => GetRawValue(context, data) == 1;