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.