MarkShark 27 Posted February 27, 2022 Hi all! I'm doing the following to convert a string to utf8 and then to move it into a memory location (it happens to be a globalallocbuffer for a clipboard format, but I don't' think that matters to my question.) It works well, but I was wondering if it's possible to do it without the intermediate byte array. Delphi 11 btw. Any thoughts appreciated. Buf := TEncoding.UTF8.GetBytes(AString); Move(Buf, PtrData^, Length(Buf)); Share this post Link to post
jbg 239 Posted February 27, 2022 TEncoding has a GetBytes() method that accepts PWideChar and PByte. Unfortunately it is "strict protected". So you would have to derive a class from TUTF8Encoding and then use that. Alternatively you can use the LocaleCharsFromUnicode system function. ByteCount := TEncoding.UTF8.GetByteCount(S); Buf := GlobalAllocPtr(0, ByteCount); if ByteCount > 0 then LocaleCharsFromUnicode(CP_UTF8, 0, PChar(S), Length(S), MarshaledAString(Buf), ByteCount, nil, nil); GlobalFreePtr(Buf); Example for a derived TUTF8Encoding class: type TUTF8EncodingEx = class(TUTF8Encoding) public // make the PWideChar/PByte methods public function GetByteCount(Chars: PWideChar; CharCount: Integer): Integer; override; function GetBytes(Chars: PWideChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer; override; function GetCharCount(Bytes: PByte; ByteCount: Integer): Integer; override; function GetChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; override; end; { TUTF8EncodingEx } function TUTF8EncodingEx.GetByteCount(Chars: PWideChar; CharCount: Integer): Integer; begin Result := inherited GetByteCount(Chars, CharCount); end; function TUTF8EncodingEx.GetBytes(Chars: PWideChar; CharCount: Integer; Bytes: PByte; ByteCount: Integer): Integer; begin Result := inherited GetBytes(Chars, CharCount, Bytes, ByteCount); end; function TUTF8EncodingEx.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer; begin Result := inherited GetCharCount(Bytes, ByteCount); end; function TUTF8EncodingEx.GetChars(Bytes: PByte; ByteCount: Integer; Chars: PWideChar; CharCount: Integer): Integer; begin Result := inherited GetChars(Bytes, ByteCount, Chars, CharCount); end; begin ByteCount := TEncoding.UTF8.GetByteCount(S); Buf := GlobalAllocPtr(0, ByteCount); if ByteCount > 0 then TUTF8EncodingEx(TEncoding.UTF8).GetBytes(PChar(S), Length(S), Buf, ByteCount); GlobalFreePtr(Buf); end; 1 1 Share this post Link to post
MarkShark 27 Posted February 28, 2022 Wow, great answer! I used the LocaleCharsFromUnicode suggestion as I ended up needing to support some other codepages. Works great! Much appreciated! Share this post Link to post