Lists of strings in KOL (TStrList, TStrListEx and others)
Of course, string lists are a very handy sort of object for storing randomly sized strings. They are also present in KOL, and are called TStrList and TStrListEx. But in KOL, these lists are not used to virtualize access to strings in Memo or RichEdit. An important difference from TStrings in VCL: strings cannot contain the # 0 character, since strings are stored exactly as character strings, terminated by a byte with code # 0. This is dictated by considerations of speed of work with large texts. Loading text (for example, from a file) into a TStrList object, or saving text to a file or stream is extremely fast and is instantaneous, even for megabytes and tens of megabytes.
The object TStrListEx differs from its TStrList ancestor (one of the rare cases in KOL when the object type is not directly inherited from TObj) in that it has an Objects property that maps each string to a 32-bit number, or a pointer (in fact, TStrListEx is built as a union of TStrList and TList, and operations on their elements are performed synchronously).
The "constructor" functions are used to create lists of strings:
NewStrList - creates an object of type TStrList, returns a pointer to it of type PStrList;
NewStrListEx - creates a TStrListEx object, returns a pointer of the PStrListEx type.
The main set of methods and properties typical for TStrList:
Count - the number of lines in the list;
Add(s) - adds a line to the end of the list;
Insert(i, s) - inserts a line at position i;
AddStrings(SL) - adds to the end of the list all lines from another object of the PStrList type;
Assign(SL) - assigns to the given list of strings the contents of the list of strings specified by the parameter;
Clear - clears the list, freeing the memory occupied by lines;
Delete(i) - deletes the line with index i;
DeleteLast - deletes the last line in the list;
IndexOf(s) - finds the string s in the list (case-sensitive), and returns the index of the found string, or -1 if the string is not found;
IndexOf_NoCase(s) - the same as the previous method, but the search for the specified string is case-insensitive (meaning the case of the Ascii encoding, the case of national characters cannot be ignored by this method);
IndexOfStrL_NoCase(s, n) - the same as the previous method, but only the first n characters of the string are compared;
Find(s, i) - performs a search in a sorted list (the method of halving is used, which increases the speed of searching in large lists of strings);
Items[i] - this property provides access to individual list items as Ansi-strings, and allows them to be read or modified;
Last - property for accessing the last line in the list (equivalent to Items [Count-1])
ItemPtrs[i]- this property, unlike Items, allows you to get the address of the beginning of the list line by its index. For the purpose of reading strings or modifying them in place, this method is preferable in terms of performance, since there is no need to allocate memory on the heap for a copy of the string. Of course, when modifying strings "in place", it is necessary to control the possible overstepping of the string when writing to it, otherwise unpleasant consequences are guaranteed. Up to the immediate crash of the application or the occurrence of a memory access exception - Access Violation, or, worse, to the corruption of the service fields of the heap manager, and the subsequent crash of the application, the causes of which are much more difficult to identify and fix;
Sort(casesensitive) - sorts strings (after which you can use the Find method, for example);
AnsiSort(casesensitive) - sorts strings as ANSI (i.e., the order of national characters is also taken into account);
Swap(i1, i2) - swaps strings in the list;
Move(i1, i2) - moves the line with index i1 to position i2;
Text - provides the ability to work with all lines of the list as one line. When reading this property, all lines - quickly - are combined into one text, consisting of lines of text separated by characters # 13 # 10, when assigning a value to this property, the original large line - quickly - is split into separate lines based on the presence of combinations of characters # 13 # 10 , # 13, # 0 at the end of each substring. An important detail: immediately after assigning a value to this property, all lines in the list are stored in a contiguous piece of memory, one after another, each ending with byte # 0. This circumstance can be used in order to perform fast processing of large texts (having received a pointer to the first line, with index 0, through the ItemPtrs [0] property, then you can "run" all lines with the pointer,
SetText(s, append) - an additional method that allows you to quickly add text from a single line, breaking it into lines in much the same way as it is done when assigning to the Text property;
SetUnixText(s, append) - similar to the previous one, but single characters # 10 (standard for Unix systems) are also considered as separators;
Join(s) - a function that returns concatenation of strings like the Text property does, but the line separator is specified by a parameter.
A special group can be divided into a set of methods for exchanging data with files and data streams:
LoadFromFile(s) - loads a list of strings from a text file;
SaveToFile(s) - saves a list of lines as text in a file;
LoadFromStream(strm) - loads a list of lines from the stream (reading it from the current position to the end of the stream);
SaveToStream(strm) - saves the list of strings to the stream (writing it from the current position in the stream);
AppendToFile(s) - adds lines from the list to the end of the specified file;
MergeFromFile(s) - adds lines from the specified file to the list of lines;
A list of strings can be used in a special way as a set of named values of the form <value_name> = <value> (similar to Ini files), and not only the '=' symbol can be used as a sign separating the value name from the value itself, but also, for example , the ':' character, and any other character. When creating the list, the symbol specified by the global variable DefaultNameDelimiter is used to initialize the delimiter, which by default stores the value '='. You can either change the value of this variable before creating the list, or you can change the NameDelimiter property of each individual list. Next, I will list the methods and properties for working with a list of strings as with a list of values:
Values[s] - this property allows you to read or change the value named s (if the name is not found during reading, an empty string is returned, if the name does not exist during writing, it is added);
IndexOfName(s) - returns the index of the string containing the value with the specified name;
LineName[i] - returns or changes (when writing) the name in the string with index i;
LineValue[i] - similarly for the value in the string with index i.
The TStrListEx object type, being an inheritor of the TStrList type, retains all these capabilities, and adds to them the ability to associate each line in the list with a numeric value, or a pointer - at will. Due to the fact that the policy of inheritance and abuse of virtual methods is not welcomed in KOL, you should not use object parameter polymorphism, and work with TStrListEx as with a TStrList object. Nothing terrible will happen (most likely), but when deleting lines, changing their order and other operations, the agreement between the lines and their associated "objects" is likely to be broken. Conclusion from the above: if you already use an object of type TStrListEx, then this object in any code that works with it must be declared exactly as TStrListEx.
All of the above methods of the TStrList object also hold for TStrListEx, but if the specialized analogs developed for TStrListEx are not used, then the object is assumed to be null (i.e. when calling Insert (i, s)a row will be inserted at position i, and the value 0 will be inserted as its object, also at position i). Below is a list of methods and properties specific to TStrListEx:
Objects[i] - access to objects associated with strings, by the string index;
LastObj - access to the last "object", equivalent to Objects [Count-1];
Assign(SLex) - assigns strings and objects from the specified extended list of strings;
AddObject(s, o) - adds a line immediately with the "object" -number associated with it;
InsertObject(i, s, o) - similar to the previous one, inserts a line together with the object, at position i;
IndexOfObj(o) - finds the first object o, and returns its index (or -1 if no such "object" is found).
In addition to the given object types for storing lists of strings, KOL also has others (but they are moved to the additional module KOLadd.pas): TFastStrListEx, TWStrList, TWStrListEx.
The TFastStrListEx object is similar in functionality to the TStrListEx type, but is optimized for fast addition of lines. In order not to clutter up this text, I will not give its detailed description here, you can always look into the source code and familiarize yourself with the set of its properties and methods.
The TWStrList and TWStrListEx objects are similar to the TStrList and TStrListEx objects, but are focused on working with Unicode strings (WideString), consisting of double-byte characters (WideChar). Therefore, it does not make much sense to describe them in detail as well, almost everything said for ordinary lists of strings is also true for these lists, except for the type of strings stored in them.
Unlike many other objects in KOL, when the UNICODE_CTRL directive is used, the TStrList and TStrListEx string lists do not automatically become UNICODE string lists. In order not to insert conditional compilation directives of the form {$ IFDEF UNICODE_CTRLS}… {$ ELSE}… {$ ENDIF} into your code, the TKOLStrList / TKOLStrListEx types are declared in KOL, which are equivalent to TStrList / TStrListEx in the case of using Ansi string types, and are replaced TWStrList / TWStrListEx in case of adding the UNICODE_CTRLS conditional compilation symbol. This is necessary because sometimes in Ansi applications you need to work with UNICODE text and (even more often) on the contrary - in a UNICODE project you need to process a "clean" Ansi list of strings.
Therefore, when creating a project that can compile with or without this option, you should use the TKOLStrList data type and the NewKOLStrList function to create it.