delphi - How can I extract part of a PChar into a string? -
during profiling came across function taking quite bit of time, boiled down simple piece of code:
function getsubstring(ainput: pchar; astart, asubstringlength: integer): string; begin result := copy(ainput, astart, asubstringlength); end;
this function returns expected sub-string, doesn't scale longer inputs. looked @ assembler code in cpu view, , can tell (i'm not working @ assembler level), seems ainput
implicitly converted string before calling copy
.
but since @ point length of string/character array unknown, conversion code has walk length of pchar
until finds null terminator. explain terrible scaling longer inputs.
however, since caller passes in length of pchar
, thought convert method use setstring
instead.
function getsubstring(ainput: pchar; astart, asubstringlength: integer): string; begin setstring(result, ainput + astart - 1, asubstringlength); end;
in addition setstring
working zero-based (not one-based copy), there seem number of other little things copy
in terms of validating inputs, not of documented (e.g. start value less 1 changed 1). naïve implementation above doesn't work original one.
my goal replicate copy
routine as possible, function part of library , has been used extensively colleagues.
i'm wondering whether following implementation accomplishes that, or whether need aware of other caveats of copy
. nb: flength
actual length of ainput
comes part in module function part of. removed other part example.
function getsubstring(ainput: pchar; astart, asubstringlength: integer): string; begin if (ainput = nil) begin result := ''; end else begin if (astart < 1) begin astart := 0; end else begin astart := astart - 1; end; if (asubstringlength + astart > flength) begin asubstringlength := flength - astart; end; setstring(result, ainput + astart, asubstringlength); end; end;
i'm using delphi 2006, assume isn't different in other versions of product (at least non-unicode ones).
let's consider corner cases. think are:
ainput
invalid.astart < 1
.astart > flength
.asubstringlength < 0
.asubstringlength + (astart-1) > flength
.
we can ignore case 1 in opinion. onus should on caller provide valid pchar
. indeed check ainput <> nil
step far in view because nil
not valid pchar
.
of rest have covered 2 , 5, not 3 , 4. if user supplies value of astart
large, read off end of string. likewise, user can readily supply negative asubstringlength
. don't think need write code check these cases since competent.
now, if care every last drop of performance, should not checking of these case. demand user passes valid parameters. in debug mode, {$ifopf d+}
or assert
might check inputs. of course, if these arguments come external sources, should validated.
on other hand, biggest performance hit original code suffers needless scanning of entire string, , copying intermediate heap allocated string. once you've removed those, have, opportunity further performance gains reduced.
Comments
Post a Comment