The Unicode Delphi string type is stored directly at its address (or "Unicode ShortString")

I need a string type, which is Unicode and which stores the string directly in the address of the variable, as is the case with the ShortString type (Ansi only).

I mean, if I declare S: ShortStringand let S := 'My String', then in @SI will find the length of the string (as a single byte, so the string cannot contain more than 255 characters). the most ANSI-encoded string.

I would like it to be a Unicode variant. That is, I want a string type such that in @SI will find a 32-bit unsigned integer (or actually there will be one byte) containing the string length in bytes (or in characters that are half the number of bytes), followed by a representation Unicode strings. I tried WideString, UnicodeStringand RawByteString, but they all appear only to store the address in @S, and the actual line is in another place (I think this is due to reference counting, etc.). Update: The most important reason for this is probably it would be very problematic if sizeof (string) were variables.

I suspect there is no built-in type to use, and that I have to come up with my own way of storing text the way I want (which is actually fun). I'm right?

Update I, among other things, should use these lines in packed records. I also need to manually read / write these lines to files / heap. I could live with fixed lines such as <= 128 characters, and I could redesign the problem to work with null characters. But PChar will not work, because sizeof (PChar) = 1 is just an address.

The approach that I finally decided was to use a static byte array. Today I will publish my implementation as a solution.

+3
source share
5 answers

, , - ( - , , , "" ):

TASStructMemHeader = packed record
  TotalSize: cardinal;
  MemType: TASStructMemType;
  Ident: packed array[0..63] of WideChar;
  DataSize: cardinal;
  procedure SetIdent(const AIdent: string);
  function ReadIdent: string;
end;

function TASStructMemHeader.ReadIdent: string;
begin
  result := WideCharLenToString(PWideChar(@(Ident[0])), length(Ident));
end;

procedure TASStructMemHeader.SetIdent(const AIdent: string);
var
  i: Integer;
begin
  if length(AIdent) > 63 then
    raise Exception.Create('Too long structure identifier.');
  FillChar(Ident[0], length(Ident) * sizeof(WideChar), 0);
  Move(AIdent[1], Ident[0], length(AIdent) * sizeof(WideChar));
end;

, array[0..63] of WideChar ,

  var
    MyStr: string;

  Ident := 'This is a sample string.';
  MyStr := Ident;

, , , , .

0

. ShortString , Unicode. , , WideString, UnicodeString WideChar, , (make byte-for-byte ), Delphi .

WideString , , , WideString ; , - . , , . , , API.

UnicodeString , , ; , , - .

WideChar , , . , , StrLCopy, .

, . , .

, . , , . ; , , . , , , , . , , , , . . "" .

+4

PChar , ? AFAIK, , , . , , Unicode Chars.

+1

unicode.
s s [1], 4 .
Length (s)?

:

procedure TForm9.Button1Click(Sender: TObject);
var
  s: string;
begin
  s := 'hlkk ljhk jhto';
  {$POINTERMATH ON}
  Assert(Length(s) = (PInteger(s)-1)^); 
  //if you don't want POINTERMATH, replace by PInteger(Cardinal(s)-SizeOf(Integer))^
  showmessage(IntToStr(length(s)));
end;
+1

Unicode ShortString. Unicode , , :

var
  buffer = array[0..255] of WideChar;

. 1, 2, .

: # 1: . , , , . ShortString , 256 (1/4 K), . , 32- , 4 . !

, , , , sizeof (). .

Why do you need to put something like this in a packed array? If I had guessed, I would say that this probably has to do with serialization. If so, you better use a TStream and a regular Unicode string and write an integer (size) to the stream and then the contents of the string. This turns out to be much more flexible than trying to embed everything in a packed array.

+1
source

Source: https://habr.com/ru/post/1744843/


All Articles