source: trunk/NewView/StringUtilsUnit.pas@ 105

Last change on this file since 105 was 105, checked in by RBRi, 18 years ago

%more stringutils refactoring

  • Property svn:eol-style set to native
File size: 14.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
[105]15 StrTAB = chr(9);
[43]16 StrCR = chr(13);
17 StrLF = chr(10);
18 StrCRLF = StrCR + StrLF;
[102]19 Quote = '''';
20 DoubleQuote = '"';
[43]21
22
23 TYPE
[35]24 TSerializableStringList = class
25 private
26 stringList : TStringList;
27
28 public
29 CONSTRUCTOR Create;
30 DESTRUCTOR Destroy; override;
31 FUNCTION getCount : LongInt;
32 PROCEDURE add(const aString : String);
33 FUNCTION get(const anIndex : LongInt) : String;
34 FUNCTION getSerializedString : String;
35 PROCEDURE readValuesFromSerializedString(const aSerializedString : String);
36 end;
37
[43]38 TYPE
39 TSetOfChars = set of char;
40
[35]41 // prefices all occurences of one of the chars in aStringWithChars with anEscape char
42 // if the escapeChar itself is found, then it is doubled
[43]43 Function StrEscapeAllCharsBy(Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char): String;
[35]44
[43]45 // Extract all fields in a String given a set of delimiter characters and
46 // an optional escape character usable to escape field delimits.
47 // Example:
[102]48 // StrExtractStrings('1x2x3\x4', 'x', '\') ->
49 // returns 4 strings: '1', '', '2' and '3x4'
[82]50 Procedure StrExtractStrings(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
[43]51
[82]52 // same as StrExtractStrings but ignores empty strings
53 Procedure StrExtractStringsIgnoreEmpty(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
54
[43]55 // removes all occurences of char from aSetOfChars from the beginning
[82]56 // of a String.
57 Function StrTrimLeftChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
58
59 // removes all occurences of char from aSetOfChars from the end
60 // of a String.
61 Function StrTrimRightChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
62
63 // removes all occurences of char from aSetOfChars from the beginning
[43]64 // end the end of a String.
65 Function StrTrimChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
66
67 // removes all blanks from beginning and end
68 Function StrTrim(const aReceiver: String): String;
69
[82]70 // Returns the aCount leftmost chars of aString
71 Function StrLeft(const aString : String; const aCount : Integer) : String;
72
[102]73 // Returns a copy of the string without aCount chars from right
74 Function StrLeftWithout(const aString : String; const aCount : Integer) : String;
75
76 // Returns a copy of the string including all characters until one from aSetOfChars found
77 Function StrLeftUntil(const aReceiver: String; const aSetOfChars: TSetOfChars) : String;
78
[105]79 // returns true if the String starts with the provided one
[102]80 // this is case SENSITIVE
81 Function StrStartsWith(const aReceiver: String; const aStartString: String): Boolean;
82
[105]83 // returns true if the String starts with the provided one
[102]84 // this is case INsensitive
85 Function StrStartsWithIgnoringCase(const aReceiver: String; const aStartString: String): Boolean;
86
[43]87 // returns true if the String ends with the provides one
88 // this is case SENSITIVE
89 Function StrEndsWith(const aReceiver: String; const anEndString: String): Boolean;
90
[105]91 // returns true if the String ends with the provided one
[43]92 // this is case INsensitive
[102]93 Function StrEndsWithIgnoringCase(const aReceiver: String; const anEndString: String): Boolean;
[43]94
[105]95 // returns true if the Strings are the same
96 // this is case INsensitive
97 Function StrEqualIgnoringCase(const aReceiver: String; const aSecondString: String): Boolean;
98
[68]99 // the IntToStr generates wrong results
100 // in normal cases IntToStr returns a negative value
101 // and somtimes completly wrong values
102 Function LongWordToStr(const aLongWord: LongWord) : String;
103
[65]104 Function BoolToStr(const aBoolean : boolean ): string;
[43]105
[102]106 // Returns aString enclosed in double quotes
107 Function StrInDoubleQuotes(const aString : String) : String;
[65]108
[102]109
[35]110Implementation
111
[65]112 uses
[105]113 SysUtils,
[65]114 DebugUnit;
115
[35]116 constructor TSerializableStringList.Create;
117 begin
[65]118 LogEvent(LogObjConstDest, 'TSerializableStringList createdestroy');
119
[35]120 inherited Create;
121 stringList := TStringList.Create;
122 end;
123
124
125 destructor TSerializableStringList.Destroy;
126 begin
[65]127 LogEvent(LogObjConstDest, 'TSerializableStringList destroy');
128 if Nil <> stringList then stringList.Destroy;
129
[35]130 inherited Destroy;
131 end;
132
133
134 FUNCTION TSerializableStringList.getCount : LongInt;
135 begin
136 result := stringList.count;
137 end;
138
139
140 PROCEDURE TSerializableStringList.add(const aString : String);
141 begin
142 stringList.add(aString);
143 end;
144
145 FUNCTION TSerializableStringList.get(const anIndex : LongInt) : String;
146 begin
147 result := stringList[anIndex];
148 end;
149
150 FUNCTION TSerializableStringList.getSerializedString : String;
151 Var
152 i : Integer;
153 begin
154 result := '';
[82]155 for i := 0 to stringList.count-1 do
[35]156 begin
157 if (i > 0) then result := result + '&';
[43]158 result := result + StrEscapeAllCharsBy(stringList[i], ['&'], '\');
[35]159 end;
160 end;
161
162
163 PROCEDURE TSerializableStringList.readValuesFromSerializedString(const aSerializedString : String);
[43]164 Begin
165 if (length(aSerializedString) < 1) then exit;
166
[65]167 LogEvent(LogObjConstDest, 'readValuesFromSerializedString');
168 stringList.Destroy;
169 LogEvent(LogObjConstDest, 'readValuesFromSerializedString destroy done');
[43]170 stringList := TStringList.Create;
171 StrExtractStrings(stringList, aSerializedString, ['&'], '\');
172 end;
173
174
175 // ----------------------------------------------------------
176
177
178 Function StrEscapeAllCharsBy(Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char): String;
[35]179 Var
180 i : Integer;
[43]181 tmpChar : Char;
182 Begin
183 Result := '';
184
185 for i := 1 To length(aReceiver) do
186 begin
187 tmpChar := aReceiver[i];
188
189 if (tmpChar = anEscapeChar) or (tmpChar IN aSetOfChars) then
190 result := result + anEscapeChar + tmpChar
191 else
192 result := result + tmpChar;
193 end;
194 end;
195
196
[82]197 Procedure PrivateStrExtractStrings( Var aResult: TStrings;
198 const aReceiver: String;
199 const aSetOfChars: TSetOfChars;
200 const anEscapeChar: char;
201 const anIgnoreEmptyFlag : boolean);
[43]202 Var
203 i : Integer;
[35]204 tmpChar,tmpNextChar : Char;
205 tmpPart: String;
[43]206 Begin
207 if (length(aReceiver) < 1) then exit;
[35]208
209 tmpPart := '';
210
211 i := 1;
[43]212 while i <= length(aReceiver) do
[35]213 begin
[43]214 tmpChar := aReceiver[i];
215 if i < length(aReceiver) then
216 tmpNextChar := aReceiver[i+1]
[35]217 else
218 tmpNextChar := #0;
219
[43]220 if (tmpChar = anEscapeChar) and (tmpNextChar = anEscapeChar) then
[35]221 begin
[43]222 tmpPart := tmpPart + anEscapeChar;
[35]223 i := i + 2;
224 end
225 else
[43]226 if (tmpChar = anEscapeChar) and (tmpNextChar IN aSetOfChars) then
[35]227 begin
[43]228 tmpPart := tmpPart + tmpNextChar;
[35]229 i := i + 2;
230 end
231 else
[43]232 if (tmpChar IN aSetOfChars) then
[35]233 begin
[82]234 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
235 begin
236 aResult.add(tmpPart);
237 end;
[35]238 tmpPart := '';
239 i := i + 1;
240 end
241 else
242 begin
243 tmpPart := tmpPart + tmpChar;
244 i := i + 1;
245 end;
246 end;
[82]247
248 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
249 begin
250 aResult.add(tmpPart);
251 end;
[35]252 end;
253
254
[82]255 Procedure StrExtractStrings(Var aResult: TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
256 Begin
257 PrivateStrExtractStrings(aResult, aReceiver, aSetOfChars, anEscapeChar, false);
258 end;
259
260
261 Procedure StrExtractStringsIgnoreEmpty(Var aResult: TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
262 Begin
263 PrivateStrExtractStrings(aResult, aReceiver, aSetOfChars, anEscapeChar, true);
264 end;
265
266
267 Function StrTrimLeftChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
268 Var
269 i : Longint;
270 Begin
271 i := 1;
272 // mem optimization
273 if aReceiver[i] in aSetOfChars then
274 begin
275 while i <= Length(aReceiver) do
276 begin
277 if aReceiver[i] in aSetOfChars then
278 inc(i)
279 else
280 break;
281 end;
282 result := Copy(aReceiver, i, Length(aReceiver)-i+1);
283 end
284 else
285 begin
286 result := aReceiver;
287 end;
288 end;
289
290
291 Function StrTrimRightChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
292 Var
293 i : Longint;
294 Begin
295 i := Length(aReceiver);
296
297 // mem optimization
298 if aReceiver[i] in aSetOfChars then
299 begin
300 while i > 0 do
301 begin
302 if aReceiver[i] in aSetOfChars then
303 dec(i)
304 else
305 break;
306 end;
307 result := Copy(aReceiver, 1, i);
308 end
309 else
310 begin
311 result := aReceiver;
312 end;
313 end;
314
315
[43]316 Function StrTrimChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
[35]317 Var
[43]318 i : Longint;
319 j : Longint;
[82]320 tmpNeedCopy : boolean;
[35]321 Begin
[82]322 tmpNeedCopy := false;
[43]323 i := 1;
324 while i < Length(aReceiver) do
325 begin
326 if aReceiver[i] in aSetOfChars then
[82]327 begin
328 inc(i);
329 tmpNeedCopy := true;
330 end
331 else
332 begin
333 break;
334 end;
[43]335 end;
[35]336
[43]337 j := Length(aReceiver);
338 while j >= i do
[35]339 begin
[43]340 if aReceiver[j] in aSetOfChars then
[82]341 begin
342 dec(j);
343 tmpNeedCopy := true;
344 end
[43]345 else
[82]346 begin
[43]347 break;
[82]348 end;
[43]349 end;
350
[82]351 if tmpNeedCopy then
352 begin
353 result := Copy(aReceiver, i, j-i+1);
354 end
355 else
356 begin
357 result := aReceiver;
358 end;
[43]359 end;
360
361
362 Function StrTrim(const aReceiver: String): String;
363 Begin
364 result := StrTrimChars(aReceiver, [' ']);
365 end;
366
367
[82]368 Function StrLeft(const aString : String; const aCount : Integer) : String;
369 Begin
370 if aCount >= Length(aString) then
371 Result := aString
372 else
373 Result := copy(aString, 1, aCount);
374 end;
375
376
[102]377 Function StrLeftWithout(const aString : String; const aCount : Integer) : String;
378 Begin
379 Result:= copy(aString, 1, length(aString) - aCount );
380 End;
381
382
383 Function StrLeftUntil(const aReceiver: String; const aSetOfChars: TSetOfChars) : String;
384 Var
385 i : integer;
386 Begin
387 Result := aReceiver;
388
389 for i := 1 To Length(aReceiver) do
390 begin
391 if aReceiver[i] in aSetOfChars then
392 begin
393 Result := Copy(aReceiver, 1, i-1 );
394 break;
395 end;
396 end;
397 end;
398
399
400 Function StrStartsWith(const aReceiver: String; const aStartString: String) : Boolean;
401 Var
402 tmpStringPos : integer;
403 tmpStartStringLength : integer;
404 Begin
405 tmpStartStringLength := Length(aStartString);
406
407 if Length(aReceiver) < tmpStartStringLength then
408 begin
409 result := false;
410 exit;
411 end;
412
413 for tmpStringPos := 1 to tmpStartStringLength do
414 begin
415 if aReceiver[tmpStringPos] <> aStartString[tmpStringPos] then
416 begin
417 result := false;
418 exit;
419 end;
420 end;
421
422 result := true;
423 end;
424
425
426 Function StrStartsWithIgnoringCase(const aReceiver: String; const aStartString: String) : Boolean;
427 Var
428 tmpStringPos : integer;
429 tmpStartStringLength : integer;
430 Begin
431 tmpStartStringLength := Length(aStartString);
432
433 if Length(aReceiver) < tmpStartStringLength then
434 begin
435 result := false;
436 exit;
437 end;
438
439 for tmpStringPos := 1 to tmpStartStringLength do
440 begin
441 if UpCase(aReceiver[tmpStringPos]) <> UpCase(aStartString[tmpStringPos]) then
442 begin
443 result := false;
444 exit;
445 end;
446 end;
447
448 result := true;
449 end;
450
451
[43]452 Function StrEndsWith(const aReceiver: String; const anEndString: String): Boolean;
453 Var
454 tmpStringPos : Longint;
455 tmpMatchPos : Longint;
456 Begin
457 tmpStringPos := length(aReceiver);
458 tmpMatchPos := length(anEndString);
459
460 if tmpMatchPos > tmpStringPos then
461 begin
462 result := false;
463 exit;
464 end;
465
466 while tmpMatchPos > 0 do
467 begin
468 if aReceiver[tmpStringPos] <> anEndString[tmpMatchPos] then
[35]469 begin
[43]470 result := false;
471 exit;
472 end;
473 dec(tmpMatchPos);
474 dec(tmpStringPos);
475 end;
[35]476
[43]477 result := true;
478 end;
479
480
481 Function StrEndsWithIgnoringCase(const aReceiver: String; const anEndString: String): Boolean;
482 Var
483 tmpStringPos : Longint;
484 tmpMatchPos : Longint;
485 Begin
[102]486 tmpStringPos := length(aReceiver);
[43]487 tmpMatchPos := length(anEndString);
488
489 if tmpMatchPos > tmpStringPos then
490 begin
491 result := false;
492 exit;
493 end;
494
495 while tmpMatchPos > 0 do
496 begin
[102]497 if upcase(aReceiver[tmpStringPos]) <> upcase(anEndString[tmpMatchPos]) then
[43]498 begin
499 result := false;
500 exit;
[35]501 end;
[43]502 dec(tmpMatchPos);
503 dec(tmpStringPos);
[35]504 end;
[43]505
506 result := true;
[35]507 end;
508
[102]509
[105]510 Function StrEqualIgnoringCase(const aReceiver: String; const aSecondString: String): Boolean;
511 begin
512 Result := CompareText(aReceiver, aSecondString) = 0;
513 end;
514
515
[68]516 Function LongWordToStr(const aLongWord: LongWord) : String;
517 Var
518 l : LongWord;
519 i : Integer;
520 Begin
521 Result := '';
522 l := aLongWord;
523
524 if l = 0 then
525 begin
526 result := '0';
527 exit;
528 end;
529
530 while l > 0 do
531 begin
532 i := l mod 10;
533 l := l div 10;
534 Case i of
535 0 : result := '0' + result;
536 1 : result := '1' + result;
537 2 : result := '2' + result;
538 3 : result := '3' + result;
539 4 : result := '4' + result;
540 5 : result := '5' + result;
541 6 : result := '6' + result;
542 7 : result := '7' + result;
543 8 : result := '8' + result;
544 9 : result := '9' + result;
545 end;
546 end;
547
548 end;
549
550
[65]551 Function BoolToStr(const aBoolean : boolean ): string;
552 begin
553 if aBoolean then
554 Result := 'True'
555 else
556 Result := 'False';
557 end;
558
[102]559 Function StrInDoubleQuotes(const aString : String) : String;
560 begin
561 Result := DoubleQuote + aString + DoubleQuote;
562 end;
563
564
[35]565END.
Note: See TracBrowser for help on using the repository browser.