source: trunk/NewView/StringUtilsUnit.pas@ 82

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

file util refactoring and many more unit tests

  • Property svn:eol-style set to native
File size: 11.0 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
19
20 TYPE
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
35 TYPE
36 TSetOfChars = set of char;
37
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
40 Function StrEscapeAllCharsBy(Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char): String;
41
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"
47 Procedure StrExtractStrings(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
48
49 // same as StrExtractStrings but ignores empty strings
50 Procedure StrExtractStringsIgnoreEmpty(Var aResult : TStrings; Const aReceiver: String; const aSetOfChars: TSetOfChars; const anEscapeChar: char);
51
52 // removes all occurences of char from aSetOfChars from the beginning
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
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
67 // Returns the aCount leftmost chars of aString
68 Function StrLeft(const aString : String; const aCount : Integer) : String;
69
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
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
83 Function BoolToStr(const aBoolean : boolean ): string;
84
85
86Implementation
87
88 uses
89 DebugUnit;
90
91 constructor TSerializableStringList.Create;
92 begin
93 LogEvent(LogObjConstDest, 'TSerializableStringList createdestroy');
94
95 inherited Create;
96 stringList := TStringList.Create;
97 end;
98
99
100 destructor TSerializableStringList.Destroy;
101 begin
102 LogEvent(LogObjConstDest, 'TSerializableStringList destroy');
103 if Nil <> stringList then stringList.Destroy;
104
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 := '';
130 for i := 0 to stringList.count-1 do
131 begin
132 if (i > 0) then result := result + '&';
133 result := result + StrEscapeAllCharsBy(stringList[i], ['&'], '\');
134 end;
135 end;
136
137
138 PROCEDURE TSerializableStringList.readValuesFromSerializedString(const aSerializedString : String);
139 Begin
140 if (length(aSerializedString) < 1) then exit;
141
142 LogEvent(LogObjConstDest, 'readValuesFromSerializedString');
143 stringList.Destroy;
144 LogEvent(LogObjConstDest, 'readValuesFromSerializedString destroy done');
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;
154 Var
155 i : Integer;
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
172 Procedure PrivateStrExtractStrings( Var aResult: TStrings;
173 const aReceiver: String;
174 const aSetOfChars: TSetOfChars;
175 const anEscapeChar: char;
176 const anIgnoreEmptyFlag : boolean);
177 Var
178 i : Integer;
179 tmpChar,tmpNextChar : Char;
180 tmpPart: String;
181 Begin
182 if (length(aReceiver) < 1) then exit;
183
184 tmpPart := '';
185
186 i := 1;
187 while i <= length(aReceiver) do
188 begin
189 tmpChar := aReceiver[i];
190 if i < length(aReceiver) then
191 tmpNextChar := aReceiver[i+1]
192 else
193 tmpNextChar := #0;
194
195 if (tmpChar = anEscapeChar) and (tmpNextChar = anEscapeChar) then
196 begin
197 tmpPart := tmpPart + anEscapeChar;
198 i := i + 2;
199 end
200 else
201 if (tmpChar = anEscapeChar) and (tmpNextChar IN aSetOfChars) then
202 begin
203 tmpPart := tmpPart + tmpNextChar;
204 i := i + 2;
205 end
206 else
207 if (tmpChar IN aSetOfChars) then
208 begin
209 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
210 begin
211 aResult.add(tmpPart);
212 end;
213 tmpPart := '';
214 i := i + 1;
215 end
216 else
217 begin
218 tmpPart := tmpPart + tmpChar;
219 i := i + 1;
220 end;
221 end;
222
223 if (NOT anIgnoreEmptyFlag) OR ('' <> tmpPart) then
224 begin
225 aResult.add(tmpPart);
226 end;
227 end;
228
229
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
291 Function StrTrimChars(const aReceiver: String; const aSetOfChars: TSetOfChars): String;
292 Var
293 i : Longint;
294 j : Longint;
295 tmpNeedCopy : boolean;
296 Begin
297 tmpNeedCopy := false;
298 i := 1;
299 while i < Length(aReceiver) do
300 begin
301 if aReceiver[i] in aSetOfChars then
302 begin
303 inc(i);
304 tmpNeedCopy := true;
305 end
306 else
307 begin
308 break;
309 end;
310 end;
311
312 j := Length(aReceiver);
313 while j >= i do
314 begin
315 if aReceiver[j] in aSetOfChars then
316 begin
317 dec(j);
318 tmpNeedCopy := true;
319 end
320 else
321 begin
322 break;
323 end;
324 end;
325
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;
334 end;
335
336
337 Function StrTrim(const aReceiver: String): String;
338 Begin
339 result := StrTrimChars(aReceiver, [' ']);
340 end;
341
342
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
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
369 begin
370 result := false;
371 exit;
372 end;
373 dec(tmpMatchPos);
374 dec(tmpStringPos);
375 end;
376
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;
401 end;
402 dec(tmpMatchPos);
403 dec(tmpStringPos);
404 end;
405
406 result := true;
407 end;
408
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
444 Function BoolToStr(const aBoolean : boolean ): string;
445 begin
446 if aBoolean then
447 Result := 'True'
448 else
449 Result := 'False';
450 end;
451
452END.
Note: See TracBrowser for help on using the repository browser.