source: trunk/NewView/StringUtilsUnit.pas@ 82

Last change on this file since 82 was 82, checked in by RBRi, 19 years ago

file util refactoring and many more unit tests

  • Property svn:eol-style set to native
File size: 11.0 KB
RevLine 
[35]1Unit StringUtilsUnit;
2
3// NewView - a new OS/2 Help Viewer
[75]4// Copyright 2006-2007 Ronald Brill (rbri at rbri dot de)
5// This software is released under the GNU Public License - see readme.txt
[35]6
7// Helper functions to work with strings
8
9Interface
10
11uses
12 Classes;
13
[43]14const
15 StrCR = chr(13);
16 StrLF = chr(10);
17 StrCRLF = StrCR + StrLF;
18
19
20 TYPE
[35]21 TSerializableStringList = class
22 private
23 stringList : TStringList;
24
25 public
26 CONSTRUCTOR Create;
27 DESTRUCTOR Destroy; override;
28 FUNCTION getCount : LongInt;
29 PROCEDURE add(const aString : String);
30 FUNCTION get(const anIndex : LongInt) : String;
31 FUNCTION getSerializedString : String;
32 PROCEDURE readValuesFromSerializedString(const aSerializedString : String);
33 end;
34
[43]35 TYPE
36 TSetOfChars = set of char;
37
[35]38 // prefices all occurences of one of the chars in aStringWithChars with anEscape char
39 // if the escapeChar itself is found, then it is doubled
[43]40 Function StrEscapeAllCharsBy(Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char): String;
[35]41
[43]42 // Extract all fields in a String given a set of delimiter characters and
43 // an optional escape character usable to escape field delimits.
44 // Example:
45 // StrExtractStrings('1x2x3\x4', "x", '\') ->
46 // returns 4 strings: "1", "", "2" and "3x4"
[82]47 Procedure StrExtractStrings(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
[43]48
[82]49 // same as StrExtractStrings but ignores empty strings
50 Procedure StrExtractStringsIgnoreEmpty(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
51
[43]52 // removes all occurences of char from aSetOfChars from the beginning
[82]53 // of a String.
54 Function StrTrimLeftChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
55
56 // removes all occurences of char from aSetOfChars from the end
57 // of a String.
58 Function StrTrimRightChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
59
60 // removes all occurences of char from aSetOfChars from the beginning
[43]61 // end the end of a String.
62 Function StrTrimChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
63
64 // removes all blanks from beginning and end
65 Function StrTrim(const aReceiver: String): String;
66
[82]67 // Returns the aCount leftmost chars of aString
68 Function StrLeft(const aString : String; const aCount : Integer) : String;
69
[43]70 // returns true if the String ends with the provides one
71 // this is case SENSITIVE
72 Function StrEndsWith(const aReceiver: String; const anEndString: String): Boolean;
73
74 // returns true if the String ends with the provides one
75 // this is case INsensitive
76 Function StrEndsWithIgnoringCase(const aString: String; const anEndString: String): Boolean;
77
[68]78 // the IntToStr generates wrong results
79 // in normal cases IntToStr returns a negative value
80 // and somtimes completly wrong values
81 Function LongWordToStr(const aLongWord: LongWord) : String;
82
[65]83 Function BoolToStr(const aBoolean : boolean ): string;
[43]84
[65]85
[35]86Implementation
87
[65]88 uses
89 DebugUnit;
90
[35]91 constructor TSerializableStringList.Create;
92 begin
[65]93 LogEvent(LogObjConstDest, 'TSerializableStringList createdestroy');
94
[35]95 inherited Create;
96 stringList := TStringList.Create;
97 end;
98
99
100 destructor TSerializableStringList.Destroy;
101 begin
[65]102 LogEvent(LogObjConstDest, 'TSerializableStringList destroy');
103 if Nil <> stringList then stringList.Destroy;
104
[35]105 inherited Destroy;
106 end;
107
108
109 FUNCTION TSerializableStringList.getCount : LongInt;
110 begin
111 result := stringList.count;
112 end;
113
114
115 PROCEDURE TSerializableStringList.add(const aString : String);
116 begin
117 stringList.add(aString);
118 end;
119
120 FUNCTION TSerializableStringList.get(const anIndex : LongInt) : String;
121 begin
122 result := stringList[anIndex];
123 end;
124
125 FUNCTION TSerializableStringList.getSerializedString : String;
126 Var
127 i : Integer;
128 begin
129 result := '';
[82]130 for i := 0 to stringList.count-1 do
[35]131 begin
132 if (i > 0) then result := result + '&';
[43]133 result := result + StrEscapeAllCharsBy(stringList[i], ['&'], '\');
[35]134 end;
135 end;
136
137
138 PROCEDURE TSerializableStringList.readValuesFromSerializedString(const aSerializedString : String);
[43]139 Begin
140 if (length(aSerializedString) < 1) then exit;
141
[65]142 LogEvent(LogObjConstDest, 'readValuesFromSerializedString');
143 stringList.Destroy;
144 LogEvent(LogObjConstDest, 'readValuesFromSerializedString destroy done');
[43]145 stringList := TStringList.Create;
146 StrExtractStrings(stringList, aSerializedString, ['&'], '\');
147 end;
148
149
150 // ----------------------------------------------------------
151
152
153 Function StrEscapeAllCharsBy(Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char): String;
[35]154 Var
155 i : Integer;
[43]156 tmpChar : Char;
157 Begin
158 Result := '';
159
160 for i := 1 To length(aReceiver) do
161 begin
162 tmpChar := aReceiver[i];
163
164 if (tmpChar = anEscapeChar) or (tmpChar IN aSetOfChars) then
165 result := result + anEscapeChar + tmpChar
166 else
167 result := result + tmpChar;
168 end;
169 end;
170
171
[82]172 Procedure PrivateStrExtractStrings( Var aResult: TStrings;
173 const aReceiver: String;
174 const aSetOfChars: TSetOfChars;
175 const anEscapeChar: char;
176 const anIgnoreEmptyFlag : boolean);
[43]177 Var
178 i : Integer;
[35]179 tmpChar,tmpNextChar : Char;
180 tmpPart: String;
[43]181 Begin
182 if (length(aReceiver) < 1) then exit;
[35]183
184 tmpPart := '';
185
186 i := 1;
[43]187 while i <= length(aReceiver) do
[35]188 begin
[43]189 tmpChar := aReceiver[i];
190 if i < length(aReceiver) then
191 tmpNextChar := aReceiver[i+1]
[35]192 else
193 tmpNextChar := #0;
194
[43]195 if (tmpChar = anEscapeChar) and (tmpNextChar = anEscapeChar) then
[35]196 begin
[43]197 tmpPart := tmpPart + anEscapeChar;
[35]198 i := i + 2;
199 end
200 else
[43]201 if (tmpChar = anEscapeChar) and (tmpNextChar IN aSetOfChars) then
[35]202 begin
[43]203 tmpPart := tmpPart + tmpNextChar;
[35]204 i := i + 2;
205 end
206 else
[43]207 if (tmpChar IN aSetOfChars) then
[35]208 begin
[82]209 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
210 begin
211 aResult.add(tmpPart);
212 end;
[35]213 tmpPart := '';
214 i := i + 1;
215 end
216 else
217 begin
218 tmpPart := tmpPart + tmpChar;
219 i := i + 1;
220 end;
221 end;
[82]222
223 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
224 begin
225 aResult.add(tmpPart);
226 end;
[35]227 end;
228
229
[82]230 Procedure StrExtractStrings(Var aResult: TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
231 Begin
232 PrivateStrExtractStrings(aResult, aReceiver, aSetOfChars, anEscapeChar, false);
233 end;
234
235
236 Procedure StrExtractStringsIgnoreEmpty(Var aResult: TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
237 Begin
238 PrivateStrExtractStrings(aResult, aReceiver, aSetOfChars, anEscapeChar, true);
239 end;
240
241
242 Function StrTrimLeftChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
243 Var
244 i : Longint;
245 Begin
246 i := 1;
247 // mem optimization
248 if aReceiver[i] in aSetOfChars then
249 begin
250 while i <= Length(aReceiver) do
251 begin
252 if aReceiver[i] in aSetOfChars then
253 inc(i)
254 else
255 break;
256 end;
257 result := Copy(aReceiver, i, Length(aReceiver)-i+1);
258 end
259 else
260 begin
261 result := aReceiver;
262 end;
263 end;
264
265
266 Function StrTrimRightChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
267 Var
268 i : Longint;
269 Begin
270 i := Length(aReceiver);
271
272 // mem optimization
273 if aReceiver[i] in aSetOfChars then
274 begin
275 while i > 0 do
276 begin
277 if aReceiver[i] in aSetOfChars then
278 dec(i)
279 else
280 break;
281 end;
282 result := Copy(aReceiver, 1, i);
283 end
284 else
285 begin
286 result := aReceiver;
287 end;
288 end;
289
290
[43]291 Function StrTrimChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
[35]292 Var
[43]293 i : Longint;
294 j : Longint;
[82]295 tmpNeedCopy : boolean;
[35]296 Begin
[82]297 tmpNeedCopy := false;
[43]298 i := 1;
299 while i < Length(aReceiver) do
300 begin
301 if aReceiver[i] in aSetOfChars then
[82]302 begin
303 inc(i);
304 tmpNeedCopy := true;
305 end
306 else
307 begin
308 break;
309 end;
[43]310 end;
[35]311
[43]312 j := Length(aReceiver);
313 while j >= i do
[35]314 begin
[43]315 if aReceiver[j] in aSetOfChars then
[82]316 begin
317 dec(j);
318 tmpNeedCopy := true;
319 end
[43]320 else
[82]321 begin
[43]322 break;
[82]323 end;
[43]324 end;
325
[82]326 if tmpNeedCopy then
327 begin
328 result := Copy(aReceiver, i, j-i+1);
329 end
330 else
331 begin
332 result := aReceiver;
333 end;
[43]334 end;
335
336
337 Function StrTrim(const aReceiver: String): String;
338 Begin
339 result := StrTrimChars(aReceiver, [' ']);
340 end;
341
342
[82]343 Function StrLeft(const aString : String; const aCount : Integer) : String;
344 Begin
345 if aCount >= Length(aString) then
346 Result := aString
347 else
348 Result := copy(aString, 1, aCount);
349 end;
350
351
[43]352 Function StrEndsWith(const aReceiver: String; const anEndString: String): Boolean;
353 Var
354 tmpStringPos : Longint;
355 tmpMatchPos : Longint;
356 Begin
357 tmpStringPos := length(aReceiver);
358 tmpMatchPos := length(anEndString);
359
360 if tmpMatchPos > tmpStringPos then
361 begin
362 result := false;
363 exit;
364 end;
365
366 while tmpMatchPos > 0 do
367 begin
368 if aReceiver[tmpStringPos] <> anEndString[tmpMatchPos] then
[35]369 begin
[43]370 result := false;
371 exit;
372 end;
373 dec(tmpMatchPos);
374 dec(tmpStringPos);
375 end;
[35]376
[43]377 result := true;
378 end;
379
380
381 Function StrEndsWithIgnoringCase(const aReceiver: String; const anEndString: String): Boolean;
382 Var
383 tmpStringPos : Longint;
384 tmpMatchPos : Longint;
385 Begin
386 tmpStringPos := length(aString);
387 tmpMatchPos := length(anEndString);
388
389 if tmpMatchPos > tmpStringPos then
390 begin
391 result := false;
392 exit;
393 end;
394
395 while tmpMatchPos > 0 do
396 begin
397 if upcase(aString[tmpStringPos]) <> upcase(anEndString[tmpMatchPos]) then
398 begin
399 result := false;
400 exit;
[35]401 end;
[43]402 dec(tmpMatchPos);
403 dec(tmpStringPos);
[35]404 end;
[43]405
406 result := true;
[35]407 end;
408
[68]409 Function LongWordToStr(const aLongWord: LongWord) : String;
410 Var
411 l : LongWord;
412 i : Integer;
413 Begin
414 Result := '';
415 l := aLongWord;
416
417 if l = 0 then
418 begin
419 result := '0';
420 exit;
421 end;
422
423 while l > 0 do
424 begin
425 i := l mod 10;
426 l := l div 10;
427 Case i of
428 0 : result := '0' + result;
429 1 : result := '1' + result;
430 2 : result := '2' + result;
431 3 : result := '3' + result;
432 4 : result := '4' + result;
433 5 : result := '5' + result;
434 6 : result := '6' + result;
435 7 : result := '7' + result;
436 8 : result := '8' + result;
437 9 : result := '9' + result;
438 end;
439 end;
440
441 end;
442
443
[65]444 Function BoolToStr(const aBoolean : boolean ): string;
445 begin
446 if aBoolean then
447 Result := 'True'
448 else
449 Result := 'False';
450 end;
451
[35]452END.
Note: See TracBrowser for help on using the repository browser.