diff --git a/MultiTerm.Core/Model/MultiFormatString.cs b/MultiTerm.Core/Model/MultiFormatString.cs index a7917dc..0337b77 100644 --- a/MultiTerm.Core/Model/MultiFormatString.cs +++ b/MultiTerm.Core/Model/MultiFormatString.cs @@ -1,4 +1,5 @@ using MultiTerm.Core.Types; +using System.Text; namespace MultiTerm.Core.Model; @@ -8,8 +9,11 @@ public class MultiFormatString public void Add(FormatType format, string value) { - // TODO check if value is valid - this.FormatValuePairs.Add(Tuple.Create(format, value)); + // check if value is valid, if yes add to FormatValuePairs + if (ValidateValue(format, value)) + { + this.FormatValuePairs.Add(Tuple.Create(format, value)); + } } public void Remove(int amount) @@ -28,8 +32,140 @@ public class MultiFormatString this.FormatValuePairs.RemoveRange( (listCount - amount) , amount); } + // TODO Setup Unit Tests public override string ToString() { - throw new NotImplementedException(); + StringBuilder stringBuilder = new(); + string hexConversionCharacters = String.Empty, binaryConversionCharacters = String.Empty; + + // parameter == null will force ending + void finalizeHexConversion(Tuple? formatValuePair) + { + // hex conversion ongoing? + if (String.IsNullOrEmpty(hexConversionCharacters) == false) + { + // ending conversion or reached limit of characters? + if (formatValuePair == null || + formatValuePair.Item1 != FormatType.Hexadecimal || + hexConversionCharacters.Count() == 4) + { + // finalize conversion + stringBuilder.Append(FromHexString(hexConversionCharacters)); + // reset ongoing conversion + hexConversionCharacters = String.Empty; + } + } + } + + // parameter == null will force ending + void finalizeBinaryConversion(Tuple? formatValuePair) + { + // binary conversion ongoing? + if (String.IsNullOrEmpty(binaryConversionCharacters) == false) + { + // ending conversion or reached limit of characters? + if (formatValuePair == null || + formatValuePair.Item1 != FormatType.Binary || + binaryConversionCharacters.Count() == 16) + { + // finalize conversion + stringBuilder.Append(FromBinaryString(binaryConversionCharacters)); + // reset ongoing conversion + binaryConversionCharacters = String.Empty; + } + } + } + + foreach (var formatValuePair in this.FormatValuePairs) + { + finalizeHexConversion(formatValuePair); + finalizeBinaryConversion(formatValuePair); + + switch (formatValuePair.Item1) // switch by format + { + case FormatType.Character: + stringBuilder.Append(formatValuePair.Item2); + break; + + case FormatType.Hexadecimal: + hexConversionCharacters += formatValuePair.Item2; + break; + + case FormatType.Binary: + binaryConversionCharacters += formatValuePair.Item2; + break; + + default: + throw new NotImplementedException($"'{nameof(ToString)}()' does not implement conversion for format {formatValuePair.Item1}"); + } + } + + finalizeHexConversion(null); + finalizeBinaryConversion(null); + + return stringBuilder.ToString(); } + + + public static bool ValidateValue(FormatType format, string value) + { + // invalid if more than one character + if(value.Count() > 1) + { return false; } + + // extract character + var character = value.First(); + + switch (format) + { + case FormatType.Character: + return true; + + case FormatType.Hexadecimal: + if (character >= '0' && character <= '9' || + character >= 'A' && character <= 'F' || + character >= 'a' && character <= 'f') + { return true; } + else + { return false; }; + + case FormatType.Binary: + if (character == '0' || character == '1') + { return true; } + else + { return false; }; + + default: + throw new NotImplementedException($"'{nameof(ValidateValue)}()' does not implement validation for format {format}"); + } + } + + // from: https://stackoverflow.com/questions/724862/converting-from-hex-to-string + // test with: returns: "Hello world" for "48656C6C6F20776F726C64" + // see https://www.fileformat.info/info/charset/UTF-16/list.htm + public static string FromHexString(string hexString) + { + // Added PadLeft so strings with one character do not get ignored + string internalHexString = hexString.PadLeft(4, '0'); + var bytes = new byte[internalHexString.Length / 2]; + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = Convert.ToByte(internalHexString.Substring(i * 2, 2), 16); + } + + return Encoding.BigEndianUnicode.GetString(bytes); + } + + public static string FromBinaryString(string binaryString) + { + string internalBinaryString = binaryString.PadLeft(16, '0'); + var bytes = new byte[internalBinaryString.Length / 8]; + for (var i = 0; i < bytes.Length; i++) + { + bytes[i] = Convert.ToByte(internalBinaryString.Substring(i * 8, 8), 2); + } + + return Encoding.BigEndianUnicode.GetString(bytes); + } + } diff --git a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs index 864373a..b72c5bd 100644 --- a/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs +++ b/MultiTerm.Core/ViewModel/SendReceiveViewModel.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using MultiTerm.Core.Model; using MultiTerm.Core.Types; @@ -20,4 +21,19 @@ public partial class SendReceiveViewModel : TerminalViewModel /// [ObservableProperty] private MultiFormatString sendData = new(); + + /// + /// Temporary sent data property, for testing purposes. + /// + [ObservableProperty] + private string sentData = string.Empty; + + /// + /// Send command. + /// + [RelayCommand] + private void Send() + { + this.SentData = this.SendData.ToString(); + } } diff --git a/MultiTerm.Wpf/View/SendReceiveView.xaml b/MultiTerm.Wpf/View/SendReceiveView.xaml index 7d3a303..8a9c6bc 100644 --- a/MultiTerm.Wpf/View/SendReceiveView.xaml +++ b/MultiTerm.Wpf/View/SendReceiveView.xaml @@ -38,13 +38,13 @@ -