I am trying to implement these two methods to read and write strings with the specified encoding to memory.
func read(from address: Int, maxLength: Int, encoding: String.Encoding) -> String? func write(to address: Int, string: String, encoding: String.Encoding) -> Bool
For the write primitive, I implemented string to data encoding using:
string.data(using: encoding, allowLossyConversion: true)
And it works correctly, replacing any unsupported character with ?.
For the read primitive my idea was the following:
- Calculate the maximum number of bytes needed to represent a string of
maxLength
usingencoding
:
" ".maximumLengthOfBytes(using: encoding) * maxLength
- Read the data from memory into an allocated buffer of the calculated size
- Lossly decode this data into a string of the specified encoding
For this last part, I tried using:
String(data: data, encoding: encoding)
But it does not work reliably, because when an invalid character is found, it just returns nil
. The issue is that, due to the fact that data is most likely oversized compared to the actual string data required, there will be some junk, which results in the decoding to fail.
So then I tried with this:
String(decoding: data, as: Unicode.UTF8.self)
Which works, but instead of using ?s it includes invalid bytes (e.g. Hello World\0\0\0\0�\u{10}
)
Furthermore, the api is fairly different between the two constructors, and I cannot figure out if there is a standard way to convert between an encoding (String.Encoding) to something I can pass as the as:
argument in String(decoding:as:)
.