GetCapacity (s):
LongString : s.Capacity
UndiscriminatedString : MaxInt
ShortString : High (s)
FixedString : High (s) - Low (s) + 1
CString (Array) : High (s) - Low (s)
CString (Zeiger) : strlen (s)
ObjectString : s.GetCapacity
GetLength (s):
LongString : s.Length
UndiscriminatedString : s.Length
ShortString : Ord (s[0])
FixedString : c := High (s);
while (c >= Low (s)) and (s[c] = ' ') do
Dec (c);
c - Low (s) + 1
CString : strlen (s)
ObjectString : s.GetLength
SetLength (s,n):
if n > GetCapacity (s) then
if TruncateFlag then
n := GetCapacity (s)
else
Error;
LongString : s.Length := n
UndiscriminatedString : if n > s.Capacity then
begin
tmp := @s;
{ possibly round n up to m * 2^k
to avoid frequent reallocations }
New (@s, n);
Move (tmp^[1], s[1], Length (tmp^);
Dispose (tmp)
end;
s.Length := n
ShortString : s[0] := Chr (n)
FixedString : FillChar (s[Low (s) + n],
GetCapacity (s) - n, ' ')
CString : s[n] := #0
ObjectString : s.SetLength (n)
GetFirstChar (s):
LongString : @s[1]
UndiscriminatedString : @s[1]
ShortString : @s[1]
FixedString : @s[Low (s)]
CString : s
ObjectString : s.GetFirstChar
Anything else can be reduced to these, e.g. string assignment:
SetLength (Dest, GetLength (Src));
Move (GetFirstChar (Src) ^, GetFirstChar (Dest) ^, GetLength (Dest));
^^^^
(because of truncate!)
Note pointer CStrings because assignments to them (from long, undiscriminated (with appending #0) or CStrings, not from short, fixed or object strings) should set the pointer, not overwrite the memory pointed to.