Added: SkipEmptyItems parameter for Split function
This commit is contained in:
parent
64eb0b252f
commit
5a7ce7bc99
@ -25,7 +25,7 @@ package X2Utils;
|
||||
{$IMAGEBASE $400000}
|
||||
{$ENDIF IMPLICITBUILDING}
|
||||
{$DESCRIPTION 'X2Utils'}
|
||||
{$LIBSUFFIX 'DXE2'}
|
||||
{$LIBSUFFIX 'XE2'}
|
||||
{$RUNONLY}
|
||||
{$IMPLICITBUILD ON}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
<ProjectVersion>13.4</ProjectVersion>
|
||||
<Base>True</Base>
|
||||
<Config Condition="'$(Config)'==''">Debug</Config>
|
||||
<Platform Condition="'$(Platform)'==''">Win64</Platform>
|
||||
<Platform Condition="'$(Platform)'==''">Win32</Platform>
|
||||
<TargetedPlatforms>3</TargetedPlatforms>
|
||||
<AppType>Package</AppType>
|
||||
</PropertyGroup>
|
||||
@ -160,7 +160,13 @@
|
||||
<Source>
|
||||
<Source Name="MainSource">X2Utils.dpk</Source>
|
||||
</Source>
|
||||
<Excluded_Packages/>
|
||||
<Excluded_Packages>
|
||||
<Excluded_Packages Name="P:\algemeen\bin\DXE2\X2CLGLD.bpl">X²CL GraphicList (Designtime)</Excluded_Packages>
|
||||
<Excluded_Packages Name="P:\algemeen\bin\DXE2\X2CLMBD.bpl">X²CL MenuBar (Designtime)</Excluded_Packages>
|
||||
<Excluded_Packages Name="P:\Algemeen\bin\DXE2\unaDesignDXE2.bpl">UnameIT - Designtime</Excluded_Packages>
|
||||
<Excluded_Packages Name="$(BDSBIN)\dcloffice2k160.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||
<Excluded_Packages Name="$(BDSBIN)\dclofficexp160.bpl">Microsoft Office XP Sample Automation Server Wrapper Components</Excluded_Packages>
|
||||
</Excluded_Packages>
|
||||
</Delphi.Personality>
|
||||
<Platforms>
|
||||
<Platform value="Win64">True</Platform>
|
||||
|
@ -9,6 +9,7 @@ type
|
||||
TStringsTest = class(TTestCase)
|
||||
published
|
||||
procedure TestSplit;
|
||||
procedure TestSkipEmptyItems;
|
||||
end;
|
||||
|
||||
|
||||
@ -31,6 +32,18 @@ begin
|
||||
CheckEquals('value2', items[1], 'Items[1]');
|
||||
end;
|
||||
|
||||
|
||||
procedure TStringsTest.TestSkipEmptyItems;
|
||||
var
|
||||
items: TStringDynArray;
|
||||
|
||||
begin
|
||||
Split('/value1///value2//', '/', items, True);
|
||||
CheckEquals(2, Length(items), 'Length');
|
||||
CheckEquals('value1', items[0], 'Items[0]');
|
||||
CheckEquals('value2', items[1], 'Items[1]');
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTest('Strings', TStringsTest.Suite);
|
||||
|
||||
|
@ -78,7 +78,7 @@ type
|
||||
* @todo though optimized, it now fails on #0 characters, need
|
||||
* to determine the end by checking the AnsiString length.
|
||||
*}
|
||||
procedure Split(const ASource, ADelimiter: String; out ADest: TStringDynArray);
|
||||
procedure Split(const ASource, ADelimiter: String; out ADest: TStringDynArray; ASkipEmptyItems: Boolean = False);
|
||||
|
||||
{** Appends string parts with a specified glue value.
|
||||
*
|
||||
@ -201,7 +201,7 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure Split(const ASource, ADelimiter: String; out ADest: TStringDynArray);
|
||||
procedure Split(const ASource, ADelimiter: String; out ADest: TStringDynArray; ASkipEmptyItems: Boolean);
|
||||
// StrPos is slow. Sloooooow slow. This function may not be advanced or
|
||||
// the fastest one around, but it sure kicks StrPos' ass.
|
||||
// 11.5 vs 1.7 seconds on a 2.4 Ghz for 10.000 iterations, baby!
|
||||
@ -253,69 +253,73 @@ const
|
||||
GrowMax = 256;
|
||||
|
||||
var
|
||||
iCapacity: Integer;
|
||||
iCount: Integer;
|
||||
iDelimLen: Integer;
|
||||
iLength: Integer;
|
||||
iPos: Integer;
|
||||
iSize: Integer;
|
||||
pDelimiter: PChar;
|
||||
pLast: PChar;
|
||||
pPos: PChar;
|
||||
capacity: Integer;
|
||||
count: Integer;
|
||||
delimiterLength: Integer;
|
||||
sourceLength: Integer;
|
||||
position: Integer;
|
||||
size: Integer;
|
||||
delimiter: PChar;
|
||||
lastPos: PChar;
|
||||
currentPos: PChar;
|
||||
|
||||
begin
|
||||
// Reserve some space
|
||||
iCapacity := GrowStart;
|
||||
iCount := 0;
|
||||
SetLength(ADest, iCapacity);
|
||||
capacity := GrowStart;
|
||||
count := 0;
|
||||
SetLength(ADest, capacity);
|
||||
|
||||
iDelimLen := Length(ADelimiter);
|
||||
iLength := Length(ASource);
|
||||
iPos := -1;
|
||||
pDelimiter := PChar(ADelimiter);
|
||||
pPos := PChar(ASource);
|
||||
delimiterLength := Length(ADelimiter);
|
||||
sourceLength := Length(ASource);
|
||||
position := 0;
|
||||
delimiter := PChar(ADelimiter);
|
||||
currentPos := PChar(ASource);
|
||||
|
||||
repeat
|
||||
// Find delimiter
|
||||
pLast := pPos;
|
||||
pPos := StrPosEx(pPos, pDelimiter);
|
||||
lastPos := currentPos;
|
||||
currentPos := StrPosEx(currentPos, delimiter);
|
||||
|
||||
if pPos <> nil then
|
||||
if currentPos <> nil then
|
||||
begin
|
||||
size := (Integer(currentPos) - Integer(lastPos)) div SizeOf(Char);
|
||||
|
||||
if (size > 0) or (not ASkipEmptyItems) then
|
||||
begin
|
||||
// Make space
|
||||
Inc(iCount);
|
||||
if iCount > iCapacity then
|
||||
Inc(count);
|
||||
if count > capacity then
|
||||
begin
|
||||
if iCapacity < GrowMax then
|
||||
Inc(iCapacity, iCapacity)
|
||||
if capacity < GrowMax then
|
||||
Inc(capacity, capacity)
|
||||
else
|
||||
Inc(iCapacity, GrowMax);
|
||||
Inc(capacity, GrowMax);
|
||||
|
||||
SetLength(ADest, iCapacity);
|
||||
SetLength(ADest, capacity);
|
||||
end;
|
||||
|
||||
// Copy substring
|
||||
iSize := (Integer(pPos) - Integer(pLast)) div SizeOf(Char);
|
||||
SetString(ADest[iCount - 1], pLast, iSize);
|
||||
|
||||
// Move pointer
|
||||
Inc(pPos, iDelimLen);
|
||||
Inc(iPos, iSize + iDelimLen);
|
||||
end else
|
||||
begin
|
||||
if iPos < iLength then
|
||||
begin
|
||||
// Copy what's left
|
||||
Inc(iCount);
|
||||
if iCount > iCapacity then
|
||||
SetLength(ADest, iCount);
|
||||
|
||||
ADest[iCount - 1] := pLast;
|
||||
SetString(ADest[count - 1], lastPos, size);
|
||||
end;
|
||||
|
||||
if iCount <> iCapacity then
|
||||
// Move pointer
|
||||
Inc(currentPos, delimiterLength);
|
||||
Inc(position, size + delimiterLength);
|
||||
end else
|
||||
begin
|
||||
if position < sourceLength then
|
||||
begin
|
||||
// Copy what's left
|
||||
Inc(count);
|
||||
if count > capacity then
|
||||
SetLength(ADest, count);
|
||||
|
||||
ADest[count - 1] := lastPos;
|
||||
end;
|
||||
|
||||
if count <> capacity then
|
||||
// Shrink array
|
||||
SetLength(ADest, iCount);
|
||||
SetLength(ADest, count);
|
||||
|
||||
break;
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user