source: trunk/NewView/StringUtilsUnit.pas@ 102

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

improved StringUtilsUnit

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