TSimpleTSInfoTree

Artykuł ten zawiera kurs obsługi bazowej klasy do obsługi plików TreeStructInfo. Opisuje składowe klasy TSimpleTSInfoTree, takie jak konstruktory i destruktor oraz metody prywatne i publiczne. Przedstawia różne sposoby ich wykorzystania, obrazując dane operacje przykładami kodów oraz ewentualną zawartością plików przed i po wykonaniu danych metod, w zgodnej z formatem składni. Opisy składowych przedstawione są w takiej kolejności, w jakiej zaimplementowane są w klasie.

W opisach poszczególnych składowych klasy wykorzystywany jest poniższy termin:

Aby móc używać bazowej klasy do obsługi plików, do sekcji uses musi zostać dodany moduł TSInfoFiles. Do przedstawienia sposobów używania konstruktorów oraz metod klasy wykorzystywane są typy danych, zadeklarowane w module TSInfoTypes. Aby móc z nich skorzystać, moduł ten także należy dodać do sekcji uses.

W przykładach użyte są nazwy plików, zawierające rozszerzenia .tsinfo, oznaczające pliki w formie tekstowej, a także .tsibin, informujące o ich binarnej zawartości. Rozszerzenia te są umowne i nieobowiązkowe, stąd pliki zawierające drzewa TreeStructInfo mogą posiadać inne rozszerzenia, bądź nie posiadać ich w ogóle. Nie wpłynie to w żaden sposób na poprawność funkcjonowania mechanizmów biblioteki.

spis treści

1. tworzenie obiektów drzew

Obiekt drzewa konfiguracyjnego TreeStructInfo może być stworzony za pomocą jednego z dwóch dostępnych konstruktorów. Możliwe jest stworzenie obiektu pustego drzewa z określeniem ścieżki lub nazwy pliku oraz trybów użytkowania, ale także bez podawania takich informacji. Tworzone drzewo może być wykorzystywane tylko i wyłącznie w pamięci, jak również może zostać automatycznie zapisane do pliku dyskowego w destruktorze klasy drzewa. Stworzenie pustego drzewa służy także do późniejszego jego załadowania z danego źródła, np. pliku dyskowego lub zasobu Lazarusa.

Relatywna ścieżka pliku źródłowego lub docelowego (a także podana jego sama nazwa) oznacza, że będzie on wyszukiwany lub zostanie utworzony względem bieżącego katalogu roboczego (tzw. "working directory" lub "current directory").

1.1. tworzenie pustego drzewa

Podstawowa (bezparametrowa) wersja konstruktora umożliwia stworzenie pustego drzewa, które nie będzie posiadało zdefiniowanej ścieżki lub nazwy pliku docelowego, a także nie będzie posiadać określonego zbioru trybów użytkowania. Poniżej przykład utworzenia obiektu pustego drzewa, z wykorzystaniem bezparametrowego konstruktora:

tsiConfig := TSimpleTSInfoTree.Create();

Tak stworzony obiekt drzewa może być wykorzystywany jedynie w pamięci, dzięki czemu jego zawartość nie zostanie automatycznie zapisana do pliku dyskowego. Konstruktor ten służy do stworzenia obiektu drzewa w celu jego późniejszego załadowania z danego źródła, np. pliku dyskowego, zasobów lub bezpośrednio z listy lub strumienia, a także daje możliwość późniejszego jego eksportu, zarówno do pliku dyskowego, jak i docelowej listy lub strumienia.

Metody umożliwiające eksport drzewa zawarte są w klasie TTSInfoTree, rozszerzającej funkcjonalność klasy bazowej.

1.2. tworzenie drzewa z określeniem nazwy pliku i trybów

Druga wersja konstruktora umożliwia stworzenie obiektu pustego drzewa ze zdefiniowaniem ścieżki lub nazwy pliku docelowego, a także określeniem zbioru trybów użytkowania. W parametrze AFileName pobiera względną (lub bezwzględną) ścieżkę lub nazwę pliku, natomiast w argumencie AModes pobiera zbiór trybów typu TTreeModes, które określać będą sposób wykorzystania drzewa.

Możliwe jest podanie pustych wartości, czyli pustego ciągu znaków nazwy pliku oraz pustego zbioru trybów:

tsiConfig := TSimpleTSInfoTree.Create('', []);

Taki zapis jest równoznaczny z wykorzystaniem bezparametrowej wersji konstruktora. Aby utworzyć obiekt drzewa, które w późniejszym czasie zostanie zapisane do pliku dyskowego, w parametrze AFileName należy podać ścieżkę lub nazwę pliku docelowego, natomiast w argumencie AModes zdefiniować zbiór trybów użytkowania:

tsiConfig := TSimpleTSInfoTree.Create('Config.tsinfo', [tmTextTree, tmAccessWrite]);

W ten sposób wywołany konstruktor utworzy nowe i puste drzewo, które w destruktorze klasy zostanie zapisane do pliku tekstowego o nazwie Config.tsinfo. Aby utworzyć obiekt pustego drzewa w pamięci, które w destruktorze zapisane zostanie do binarnego pliku, do zbioru w parametrze AModes należy dodać tryb tmBinaryTree:

tsiConfig := TSimpleTSInfoTree.Create('Config.tsibin', [tmBinaryTree, tmAccessWrite]);

Jeśli w zbiorze trybów nie zostanie podany tryb tmAccessWrite, drzewo nie zostanie automatycznie zapisane do pliku w destruktorze. Aby wymusić zapis drzewa do pliku, należy zaktualizować plik za pomocą metody UpdateFile (metodę tę można wywołać w dowolnym momencie istnienia utworzonego w pamięci obiektu).

2. zwalnianie obiektów drzew

Za zwolnienie instancji klasy odpowiada destruktor, który oprócz zwolnienia zaalokowanej dla obiektu pamięci, odpowiada także za końcową opcjonalną aktualizację pliku źródłowego lub utworzenie nowego pliku docelowego. Jeżeli drzewo zostało utworzone w celu jego późniejszego zapisu, bądź jeśli zostało załadowane z danego źródła z określeniem trybów użytkowania, możliwy jest jego zapis do pliku dyskowego.

Aby zabezpieczyć program przed utratą danych i wyciekami pamięci, zaleca się korzystanie z bloku try finally:

{ utworzenie instancji klasy drzewa }
tsiConfig := TSimpleTSInfoTree.Create('Config.tsinfo', [tmTextTree, tmAccessWrite]);
try
  { wykorzystanie drzewa konfiguracji }
finally
  { zwolnienie obiektu drzewa }
  tsiConfig.Free();
end;

Drzewo zostanie automatycznie zapisane do nowego lub źródłowego pliku jedynie w przypadku, gdy ścieżka lub nazwa pliku nie będzie pusta, a także jeżeli w zbiorze trybów użytkowania drzewa istnieje tryb tmAccessWrite.

3. ładowanie drzew z zadanego źródła

Bazowa klasa do obsługi plików TreeStructInfo oferuje możliwość załadowania pojedynczego drzewa z pięciu różnych źródeł. Klasa ta posiada zestaw metod umożliwiających załadowanie drzewa z pliku dyskowego, bezpośrednio z listy lub strumienia, a także z zasobu, w tym z zasobu kompilowanego oraz skryptowego zasobu Lazarusa.

3.1. ładowanie z pliku dyskowego

Do załadowania pojedynczego drzewa z pliku dyskowego służy metoda LoadFromFile. Pobiera ona ścieżkę lub nazwę pliku konfiguracyjnego w parametrze AFileName, a także zbiór trybów typu TTreeModes, określających formę i sposób wykorzystania drzewa.

Aby załadować drzewo z pliku tekstowego w trybie tylko do odczytu, w parametrze AFileName należy podać ścieżkę lub nazwę pliku źródłowego, natomiast zbiór z argumentu AModes domyślnie jest pusty, co oznacza załadowanie pliku tekstowego w trybie tylko do odczytu:

tsiConfig.LoadFromFile('Config.tsinfo');

Możliwe jest też zdefiniowanie tego zbioru, dodając do niego wartości tmTextTree oraz tmAccessRead, służące w tym kontekście jedynie do zwiększenia czytelności kodu:

tsiConfig.LoadFromFile('Config.tsinfo', [tmTextTree, tmAccessRead]);

Wywołanie metody w powyższy sposób także spowoduje załadowanie drzewa z pliku Config.tsinfo w trybie tylko do odczytu. Aby drzewo zostało załadowane w trybie do odczytu i zapisu (z automatyczną aktualizacją pliku źródłowego w destruktorze), należy do zbioru dodać tryb tmAccessWrite:

tsiConfig.LoadFromFile('Config.tsinfo', [tmTextTree, tmAccessWrite]);

Jeżeli drzewo ma zostać załadowane z pliku binarnego, należy użyć trybu tmBinaryTree zamiast tmTextTree:

tsiConfig.LoadFromFile('Config.tsibin', [tmBinaryTree, tmAccessWrite]);

Tak wywołana metoda spowoduje załadowanie drzewa z binarnego pliku o nazwie Config.tsibin w trybie do odczytu i zapisu.

3.2. ładowanie z listy

Do załadowania pojedynczego drzewa bezpośrednio z listy służy metoda LoadFromList. Pobiera ona w parametrze AList referencję do instancji klasy dziedziczącej po TStrings, zawierającej źródłowe linie z zapisem drzewa w postaci tekstowej. Aby załadować drzewo z listy jedynie do odczytania danych konfiguracyjnych, w tym parametrze należy przekazać utworzony w pamięci obiekt listy:

var
  slInput: TStringList;

{..}

tsiConfig.LoadFromList(slInput);

Metoda ta posiada także dwa inne parametry, które posiadają wartości domyślne. Do parametru AFileName możliwe jest przekazanie ścieżku lub nazwy pliku docelowego, natomiast w argumencie AModes — zbioru trybów określających formę pliku docelowego oraz sposób wykorzystania ładowanego drzewa.

Jeżeli ładowane ze źródłowej listy drzewo ma zostać automatycznie zapisane do pliku dyskowego w destruktorze, należy w argumencie AFileName podać ścieżkę lub nazwę pliku, a w parametrze AModes podać tryb tmAccessWrite oraz określić formę pliku docelowego:

tsiConfig.LoadFromList(slInput, 'Config.tsinfo', [tmTextTree, tmAccessWrite]);

Powyższa instrukcja spowoduje załadowanie drzewa z listy oraz umożliwi automatyczny jego zapis w destruktorze obiektu do pliku Config.tsinfo w formie tekstowej.

3.3. ładowanie ze strumienia

Do załadowania drzewa konfiguracji ze strumienia służy metoda LoadFromStream. Pobiera ona w parametrze AStream referencję do instancji klasy dziedziczącej po TStream, zawierającej zapis drzewa w postaci tekstowej lub binarnej. Metoda ta posiada także dwa parametry dodatkowe — AFileName, przyjmujący ścieżkę lub nazwę pliku docelowego, do którego drzewo zostanie zapisane w destruktorze, a także AModes, pobierający zbiór trybów, określających formę drzewa oraz sposób jego wykorzystania.

Aby załadować drzewo zapisane w strumieniu wyjściowym w formie tekstowej jedynie do odczytu danych, w parametrze AStream należy przekazać utworzony w pamięci obiekt strumienia:

var
  fsInput: TFileStream;

{..}

tsiConfig.LoadFromStream(fsInput);

Możliwe jest też podanie trybów tmTextTree oraz tmAccessRead w opcjonalnym parametrze AModes:

tsiConfig.LoadFromStream(fsInput, '', [tmTextTree, tmAccessRead]);

W przypadku ładowania drzewa w formie tekstowej ze strumienia, podanie wyżej wymienionych trybów nie jest konieczne — służyć mogą jedynie w celu zwiększenia czytelności kodu. Natomiast jeżeli strumień źródłowy zawiera zapis drzewa w formie binarnej, konieczne jest dodanie do zbioru trybu tmBinaryTree:

tsiConfig.LoadFromStream(fsInput, '', [tmBinaryTree, tmAccessRead]);

Jeśli ładowane ze źródłowego strumienia drzewo ma zostać automatycznie zapisane do pliku dyskowego w destruktorze, w argumencie AFileName konieczne jest podanie ścieżki lub nazwy pliku, a także dodanie do zbioru w parametrze AModes trybu tmAccessWrite oraz określenie formy pliku docelowego:

tsiConfig.LoadFromStream(fsInput, 'Config.tsinfo', [tmTextTree, tmAccessWrite]);

W ten sposób wywołana metoda umożliwi załadowanie drzewa w formie tekstowej ze strumienia, a także spowoduje jego automatyczny zapis do pliku Config.tsinfo w destruktorze obiektu.

3.4. ładowanie z kompilowanego zasobu

Załadowanie drzewa konfiguracji z zasobu pliku wykonywalnego lub biblioteki DLL umożliwiają dwie przeładowane metody LoadFromResource. Służą one do wczytania do pamięci drzewa z zasobu kompilowanego (dołączonego do modułu pliku .rc lub .res), zawierającego zapis tekstowego lub binarnego drzewa TreeStructInfo. Pozwalają na załadowanie drzewa na podstawie nazwy zasobu lub jego liczbowego identyfikatora.

Obie wersje metody w parametrze AInstance pobierają uchwyt do zasobów, a także typ zasobu w argumencie AResType w postaci ciągu znaków. Jeżeli drzewo ma zostać załadowane na podstawie nazwy zasobu, skorzystać należy z pierwszej wersji metody, podając w parametrze AResName nazwę zasobu z zapisanym drzewem konfiguracyjnym. Natomiast jeśli drzewo ma być wczytane na podstawie liczbowego identyfikatora zasobu, należy skorzystać z drugiej wersji metody, przekazując w argumencie AResID wspomniany identyfikator.

Aby załadować drzewo w formie tekstowej z zasobów aplikacji na podstawie nazwy zasobu, w argumencie AInstance przekazać należy uchwyt do zasobów, w argumencie AResName podać nazwę zasobu oraz przekazać w parametrze AResType łańcuch z jego typem:

tsiConfig.LoadFromResource(HInstance(), 'Config', 'RT_TSINFO');

Metoda wywołana w powyższy sposób spowoduje załadowanie drzewa konfiguracyjnego z zasobów uruchomionej aplikacji, gdzie nazwa zasobu to Config, a jego typ to RT_TSINFO. Jeżeli zasób zamiast nazwy posiada liczbowy identyfikator, należy skorzystać z drugiej wersji metody i podać go w argumencie AResID:

tsiConfig.LoadFromResource(HInstance(), 10, 'RT_TSINFO');

Dzięki temu drzewo zostanie załadowane z zasobów, odwołując się za pomocą ID o wartości 10.

Metody te posiadają także dodatkowe parametry z wartościami domyślnymi. Parametr AFileName przyjmuje ścieżkę lub nazwę pliku docelowego, do którego drzewo może zostać zapisane w destruktorze, natomiast argument AModes pobiera zbiór trybów określających formę drzewa oraz sposób jego wykorzystania. Aby drzewo zostało automatycznie zapisane do pliku docelowego, w parametrze AFileName podać należy ścieżkę lub nazwę pliku, a także w argumencie AModes podać zbiór trybów z dodanym trybem tmAccessWrite.

Poniżej przykład załadowania drzewa w formie binarnej z zasobów uruchomionej aplikacji, na podstawie nazwy zasobu i z umożliwieniem jego automatycznego zapisu do pliku dyskowego w destruktorze:

tsiConfig.LoadFromResource(HInstance(), 'Config', 'RT_TSINFO', 'Config.tsinfo', [tmTextTree, tmAccessWrite]);

oraz przykład załadowania pliku binarnego, na podstawie liczbowego identyfikatora:

tsiConfig.LoadFromResource(HInstance(), 10, 'RT_TSINFO', 'Config.tsibin', [tmBinaryTree, tmAccessWrite]);

Metody te umożliwiają także załadowanie drzewa konfiguracyjnego, znajdującego się w zasobach biblioteki DLL. Aby załadować drzewo z zasobów takiej biblioteki, w parametrze AInstance przekazać należy do niej uchwyt. Poniżej przykład załadowania drzewa w formie tekstowej z zasobów biblioteki DLL, na podstawie nazwy zasobu, jedynie do odczytu danych konfiguracyjnych:

uses
  DynLibs;

{..}

var
  lhSourceDLL: TLibHandle;

{..}

lhSourceDLL := LoadLibrary('test.dll');

if lhSourceDLL <> NilHandle then
try
  tsiConfig := TSimpleTSInfoTree.Create();
  try
    tsiConfig.LoadFromResource(lhSourceDLL, 'Config', 'RT_TSINFO');

    { wykorzystanie drzewa konfiguracji }
  finally
    tsiConfig.Free();
  end;
finally
  UnloadLibrary(lhSourceDLL);
end;

3.5. ładowanie ze skryptowego zasobu Lazarusa

Do załadowania drzewa z zasobu Lazarusa służy metoda LoadFromLazarusResource, umożliwiająca załadowanie drzewa w formie tekstowej i binarnej. Pobiera ona w parametrze AResName nazwę zasobu oraz jego typ w argumencie AResType. Poniżej przykład ładowania drzewa tekstowego z zasobu skryptowego, jedynie do odczytu danych konfiguracyjnych:

tsiConfig.LoadFromLazarusResource('Config', 'LRT_TSINFO');

Wywołanie metody w taki sposób spowoduje załadowanie drzewa tekstowego z zasobu o nazwie Config oraz typie LRT_TSINFO.

Metoda ta posiada także dodatkowe parametry z wartościami domyślnymi. Argument AFileName służy do określenia ścieżki lub nazwy pliku docelowego, do którego może zostać zapisane drzewo w destruktorze, natomiast parametr AModes przyjmuje zbiór trybów, określających formę drzewa oraz sposób jego wykorzystania. Jeżeli drzewo ma zostać automatycznie zapisane do pliku dyskowego w destruktorze, ścieżka lub nazwa pliku docelowego musi być określona, natomiast zbiór trybów musi zawierać tryb tmAccessWrite.

Poniżej przykład załadowania drzewa w formie binarnej z zasobu Lazarusa, z umożliwieniem jego późniejszego zapisu do pliku dyskowego:

tsiConfig.LoadFromLazarusResource('Config', 'LRT_TSIBIN', 'Config.tsibin', [tmBinaryTree, tmAccessWrite]);

Powyższa instrukcja spowoduje załadowanie drzewa w formie binarnej z zasobu o nazwie Config oraz typie LRT_TSIBIN. Drzewo zostanie automatycznie zapisane do pliku binarnego o nazwie Config.tsibin tuż przed zwolnieniem obiektu z pamięci.

4. operacje na węzłach

Do możliwych operacji na pojedynczym węźle zalicza się przede wszystkim możliwość jego otwarcia. Istnieje możliwość otwarcia dowolnego węzła potomnego w dwóch trybach — w trybie do odczytu i zapisu, dając możliwość modyfikacji zawartości, ale też w trybie tylko do odczytu, który blokuje możliwość wprowadzania zmian. Każdy uprzednio otwarty węzeł można zamknąć lub skorzystać z odpowiedniej metody, umożliwiającej przejście do węzła-rodzica względem aktualnie otwartego węzła.

Otwieranie węzłów służy przede wszystkim do łatwiejszego dostępu do zawartych w nich elementów. Dzięki temu wyklucza się konieczność podawania pełnych ścieżek dostępu do elementów.

4.1. otwieranie węzła

Do otwarcia dowolnego węzła potomnego służy metoda OpenChildNode, umożliwiająca jego otwarcie na podstawie zadanej ścieżki lub nazwy, przekazywanej w parametrze ANodePath. Metoda ta posiada też parametry dodatkowe z wartościami domyślnymi. Parametr AReadOnly służy do określenia czy węzeł ma zostać otwarty w trybie tylko do odczytu, natomiast argument ACanCreate umożliwia utworzenie pełnej ścieżki węzłów, jeśli otwierany węzeł nie istnieje w drzewie.

Przykładowy plik konfiguracyjny TreeStructInfo posiada poniższą zawartość:

treestructinfo "2.0"
  node First
    node Second
    end node
  end node
end tree

Aby otworzyć węzeł First w trybie do odczytu i zapisu, wystarczy podać jego ścieżkę w parametrze ANodePath:

tsiConfig.OpenChildNode('First\');

Jeżeli zawartość otwieranego węzła nie będzie modyfikowana, w parametrze AReadOnly zaleca się podać wartość True:

tsiConfig.OpenChildNode('First\Second\', True);

W przypadku gdy nie ma pewności, że dany węzeł istnieje w drzewie, skorzystać należy z parametru ACanCreate. Jeśli parametr ten zawiera domyślną wartość False, próba otwarcia nieistniejącego węzła zakończy się niepowodzeniem, węzeł nie zostanie utworzony, a metoda zwróci wartość False. Aby nieistniejący węzeł mógł zostać utworzony, w argumencie tym należy podać wartość True:

tsiConfig.OpenChildNode('First\Third\', False, True);

W ten sposób wywołana metoda spowoduje utworzenie węzła o nazwie Third, dlatego że nie istnieje on w węźle First. Węzeł ten zostanie otwarty w trybie do odczytu i zapisu, dlatego że w parametrze AReadOnly podana została wartość False.

Po wywołaniu metody, zawartość pliku konfiguracyjnego przyjmie poniższą postać:

treestructinfo "2.0"
  node First
    node Second
    end node
    node Third
    end node
  end node
end tree

4.2. zamykanie węzła

Każdy potomny węzeł otwarty za pomocą metody OpenChildNode należy zamknąć, po odczycie danych lub wprowadzeniu stosownych modyfikacji. Do tego celu służy metoda CloseChildNode. Pozwala to przywrócić możliwość odwoływania się do elementów drzewa za pomocą pełnych ścieżek dostępu.

Pominięcie zamknięcia węzła może spowodować niepoprawne działanie kolejnych instrukcji, wykorzystujących ścieżki dostępu.

Aby zabezpieczyć otwarcie węzła przed pominięciem jego zamknięcia, zaleca się skorzystanie z bloku try finally:

{ otwarcie węzła }
if tsiConfig.OpenChildNode('First\Second\') then
try
  { odczyt danych lub wprowadzenie modyfikacji }
finally
  { zamknięcie węzła }
  tsiConfig.CloseChildNode();
end;

Powyższy szablon można zastosować jedynie w przypadku, gdy węzeł ma zostać otwarty oraz zamknięty w tym samym bloku kodu.

4.3. przechodzenie do węzła-rodzica

Przechodzenie do węzła-rodzica możliwe jest za pomocą metody GoToParentNode. Jedynym parametrem tej metody jest AKeepReadOnlyMode, który określa, czy tryb otwarcia węzła tylko do odczytu ma zostać podtrzymany. Metoda ta umożliwia zmianę aktualnie otwartego węzła, co pozwoli odwoływać się do elementów potomnych względem węzła nadrzędnego.

Poniżej znajduje się zawartość przykładowego pliku konfiguracyjnego TreeStructInfo:

treestructinfo "2.0"
  node First
    node Second
    end node
  end node
end tree

Teraz otwieramy węzeł o nazwie Second w trybie tylko do odczytu, za pomocą metody OpenChildNode:

tsiConfig.OpenChildNode('First\Second\', True);

Aby zmienić aktualnie otwarty węzeł i przejść do węzła o nazwie First, należy wywołać metodę GoToParentNode:

tsiConfig.GoToParentNode();

Dzięki temu aktualnie otwartym węzłem stanie się węzeł o nazwie First, a tryb otwarcia tylko do odczytu zostanie wyłączony. Aby podtrzymać ten tryb włączony, należy przekazać w parametrze AKeepReadOnlyMode wartość True:

tsiConfig.GoToParentNode(True);

5. zapisywanie danych do atrybutów

Klasa TSimpleTSInfoTree umożliwia zapis do atrybutów danych wielu typów, zarówno prostych, takich jak wartości logiczne czy liczbowe, jak również jednoliniowych i wieloliniowych łańcuchów znaków, współrzędnych punktów, dat i czasów, dowolnych buforów, czy zawartości list dziedziczących z klasy TStrings lub zawartości strumieni dziedziczących z klasy TStream. Dane mogą być zapisywane w wielu dostępnych formatach, np. w przypadku liczb całkowitych, w jednym z kilku systemów liczbowych.

Zapis danych dokonywany jest przede wszystkim na podstawie ścieżki dostępu do atrybutu, a także opcjonalnie na podstawie formatu, określającego formę reprezentacji zapisywanych danych.

Jeżeli atrybut, do którego zapisywane są dane nie istnieje w strukturze drzewa, zostaje on utworzony. Jeśli podana ścieżka wskazuje na atrybut w nieistniejącym węźle, wszystkie nieistniejące węzły także zostają utworzone w drzewie.

Niektóre metody wykorzystują rekord typu TFormatSettings, zawierający informacje o formatowaniu łańcuchów znaków wartości przekonwertowanych liczb zmiennoprzecinkowych, waluty oraz składowych daty i czasu. Rekord ten może zawierać wartości pobrane z ustawień systemu lub własne, w zależności od wymagań.

5.1. zapis wartości logicznej

Do zapisu pojedynczej wartości logicznej do atrybutu służy metoda WriteBoolean. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz zapisywaną wartość logiczną w argumencie ABoolean. Dodatkowo pozwala na określenie formatu łańcucha wartości po konwersji, przyjmując w parametrze AFormat wartość typu TFormatBoolean.

Aby wpisać pojedynczą wartość logiczną w domyślnym formacie do atrybutu, należy przekazać w parametrze AAttrPath samą nazwę atrybutu znajdującego się w aktualnie otwartym lub głównym węźle drzewa, a także wartość w argumencie ABoolean:

tsiConfig.WriteBoolean('Boolean', True);

Po wywołaniu metody w powyższy sposób, deklaracja atrybutu w pliku przedstawiać się będzie następująco:

attr Boolean "True"

Aby wartość w pliku została zapisana w innej formie, należy przekazać w parametrze AFormat wybraną wartość formatu:

tsiConfig.WriteBoolean('First\Boolean', False, fbLongYesNo);

Wywołanie metody w powyższy sposób spowoduje zapisanie wartości False do atrybutu o nazwie Boolean, znajdującego się wewnątrz węzła o nazwie First. Deklaracja atrybutu w pliku po wpisaniu nowej wartości wyglądać będzie następująco:

attr Boolean "No"

5.2. zapis liczby całkowitej

Do zapisu pojedynczej liczby całkowitej do atrybutu służy metoda WriteInteger. Przyjmuje w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz w argumencie AInteger liczbę całkowitą. Dodatkowym parametrem jest AFormat typu TFormatInteger, dzięki któremu określić można system liczbowy, który użyty zostanie do konwersji liczby na łańcuch znaków.

Aby wpisać pojedynczą wartość całkowitoliczbową w domyślnym systemie liczbowym do atrybutu znajdującego się w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath należy podać jego samą nazwę, a także podać wartość liczbową w argumencie AInteger:

tsiConfig.WriteInteger('Integer', 254);

Po wywołaniu tej metody, deklaracja atrybutu wyglądać będzie następująco:

attr Integer "254"

Jeżeli liczba ma zostać zapisana w innym systemie liczbowym niż decymalny, w parametrze AFormat należy podać odpowiednią wartość:

tsiConfig.WriteInteger('First\Integer', 254, fiHexadecimal);

Wywołanie metody w powyższy sposób spowoduje zapisanie liczby 254 w systemie heksadecymalnym do atrybutu Integer, który zawarty jest wewnątrz węzła o nazwie First. Po tej operacji, deklaracja atrybutu przedstawiać się będzie następująco:

attr Integer "0xFE"

5.3. zapis liczby zmiennoprzecinkowej

Do zapisu liczby zmiennoprzecinkowej do atrybutu służą metody WriteFloat. Pobierają one nazwę lub ścieżkę atrybutu w parametrze AAttrPath oraz liczbę zmiennoprzecinkową w argumencie ADouble. Posiadają też parametry dodatkowe z wartościami domyślnymi — AFormat typu TFormatFloat do określenia formatu zapisu liczby oraz ASettings, przyjmujący rekord typu TFormatSettings.

Aby zapisać pojedynczą liczbę zmiennoprzecinkową w domyślnej formie do atrybutu, znajdującego się wewnątrz aktualnie otwartego lub głównego węzła drzewa, a argumencie AAttrPath przekazać należy samą jego nazwę, natomiast w parametrze ADouble podać liczbę zmiennoprzecinkową:

tsiConfig.WriteFloat('Float', 34.79);

Po wykonaniu powyższej instrukcji, deklaracja atrybutu Float wyglądać będzie następująco:

attr Float "34,79"

Jeśli liczba ma zostać zapisana w innej notacji niż dziesiętna, w argumencie AFormat przekazać należy wybraną wartość:

tsiConfig.WriteFloat('First\Float', 34.79, ffSignedExponent);

Wywołanie metody w powyższy sposób spowoduje zapis liczby 34.79 w notacji wykładniczej (z wiodącym znakiem) do atrybutu Float, znajdującego się wewnątrz węzła o nazwie First. Deklaracja atrybutu po zapisie liczby przedstawiać się będzie następująco:

attr Float "+3,47900000000000E+0001"

5.4. zapis waluty

Zapis waluty do atrybutu możliwy jest za pomocą metod WriteCurrency. Pobierają one w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz w argumencie ACurrency liczbę typu Currency. Metody te posiada także parametry dodatkowe — w argumencie AFormat typu TFormatCurrency możliwe jest określenie formy zapisu liczby, natomiast w parametrze ASettings — rekordu z danymi regionalnymi typu TFormatSettings.

Aby zapisać pojedynczą kwotę w domyślnej formie do atrybutu znajdującego się w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy samą nazwę atrybutu, natomiast w argumencie ACurrency podać odpowiednią liczbę:

tsiConfig.WriteCurrency('Currency', 12.4329);

Jeżeli nazwa waluty zawiera znaki, które w kodowaniu UTF-8 są multibajtowe, podczas gdy domyślnie nazwa ta kodowana jest w ANSI, należy skorzystać z procedury GetLocaleFormatSettings w celu pobrania danych regionalnych, a następnie wpisać łańcuch znaków kodowany w UTF-8 do pola CurrencyString rekordu:

uses
  SysUtils;

{..}

var
  fsPolish: TFormatSettings;

{..}

GetLocaleFormatSettings(1045, fsPolish);
fsPolish.CurrencyString := 'zł';

tsiConfig.WriteCurrency('Currency', 12.4329, fsPolish);

Po wywołaniu metody w jednym z powyższych sposobów, deklaracja atrybutu będzie przedstawiać się następująco:

attr Currency "12,43 zł"

Jeżeli kwota ma zostać zapisana z większą precyzją, w parametrze AFormat należy przekazać odpowiednią wartość:

tsiConfig.WriteCurrency('First\Currency', 12.4329, fsPolish, fcSignedExchangeRate);

Wywołanie metody w powyższy sposób spowoduje zapis liczby 12.4329 z wiodącym znakiem do atrybutu Currency, znajdującego się wewnątrz węzła o nazwie First:

attr Currency "+12,4329 zł"

5.5. zapis łańcucha znaków

Do zapisu łańcucha znaków do atrybutu służy metoda WriteString. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz łańcuch znaków do zapisu w argumencie AString. Metoda ta posiada także dodatkowy parametr AFormat typu TFormatString, określający wielkość znaków zapisywanego łańcucha.

Aby zapisać jednoliniowy łańcuch znaków bez zmiany wielkości znaków do atrybutu, znajdującego się w aktualnie otwartym lub głównym węźle drzewa, w argumencie AAttrPath przekazać należy samą jego nazwę, natomiast w parametrze AString podać łańcuch znaków do zapisu:

tsiConfig.WriteString('String', 'Tree Structure Information');

Po wywołaniu metody w powyższy sposób, deklaracja atrybutu przedstawiać się będzie następująco:

attr String "Tree Structure Information"

Jeżeli zapisywany łańcuch ma zostać zapisany jako wieloliniowy, poszczególne jego linie muszą być oddzielone znakami o kodzie 0x0A:

tsiConfig.WriteString('String', 'Tree'#10'Structure'#10'Information');

Po wykonaniu powyższej instrukcji, deklaracja atrybutu przedstawiać się będzie następująco:

attr String "Tree"
            "Structure"
            "Information"

Metoda WriteString pozwala także zapis łańcucha znaków, w którym możliwa jest zmiana wielkości liter. Aby tego dokonać, do parametru AFormat przekazać należy odpowiednią wartość:

tsiConfig.WriteString('First\String', 'Tree'#10'Structure'#10'Information', fsUpperCase);

Wywołanie metody w powyższy sposób spowoduje zapis wieloliniowego łańcucha w atrybucie String, znajdującego się wewnątrz węzła o nazwie First. Wielkość znaków łańcucha zostanie zmieniona, dzięki czemu deklaracja atrybutu przedstawiać się będzie następująco:

attr String "TREE"
            "STRUCTURE"
            "INFORMATION"

5.6. zapis daty i czasu

Do zapisu daty i czasu jako wartości atrybutu służą metody WriteDateTime. Pobierają one w parametrze AAttrPath ścieżkę lub nazwę atrybutu, maskę wartości w parametrze AMask oraz wartość typu TDateTime w argumencie ADateTime. Dodatkowo, rozszerzona wersja metody umożliwia przekazanie w parametrze ASettings typu TFormatSettings.

Aby zapisać składowe daty i czasu w podstawowej formie do atrybutu, znajdującego się wewnątrz aktualnie otwartego lub głównego węzła drzewa, w parametrze AAttrPath przekazać należy samą jego nazwę, następnie w argumencie AMask podać łańcuch znaków zawierający znaki określające składowe daty, a także przekazać wartość typu TDateTime w parametrze ADouble:

tsiConfig.WriteDateTime('DateTime', 'D.MM.YYYY, H:NN:SS', Now());

Po wywołaniu metody, deklaracja atrybutu przedstawiać się będzie następująco:

attr DateTime "21-11-2015, 3:13:32"

Metoda ta umożliwia także umieszczenie w wartości danych niebędących składowymi daty lub czasu. Umożliwia to zapis daty i czasu w bardziej opisowy sposób lub z możliwością odczytania danych jako zwykłego łańcucha znaków, w celu jego wyświetlenia użytkownikowi. Dane niebędące składowymi daty i czasu, muszą być objęte parą znaków " lub ' w łańcuchu maski:

tsiConfig.WriteDateTime('First\DateTime', '"Dziś jest" DDDD, D.MM.YYYY "(godzina" H:NN")"', Now());

Metoda wywołana w powyższy sposób spowoduje zapisanie wartości daty i czasu z dodatkowymi informacjami do atrybutu DateTime, znajdującego się wewnątrz węzła o nazwie First. Po zapisie danych, deklaracja atrybutu przyjmie poniższą postać:

attr DateTime "Dziś jest niedziela, 22-11-2015 (godzina 19:36)"

5.7. zapis współrzędnych punktu

Do zapisu współrzędnych punktu do atrybutu służy metoda WritePoint. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz wartość typu TPoint w argumencie APoint. Dodatkowo, metoda umożliwia określenie systemu liczbowego, w którym reprezentowana będzie liczba w wartości atrybutu — do tego celu służy parametr AFormat typu TFormatPoint. Domyślnym systemem liczbowym dla współrzędnych jest system decymalny.

Aby zapisać współrzędne punktu w domyślnym systemie liczbowym do atrybutu, znajdującego się w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath należy podać samą jego nazwę, natomiast w argumencie APoint przekazać współrzędne:

tsiConfig.WritePoint('Point', Point(1024, 768));

Po zapisie danych, deklaracja atrybutu przedstawiać się będzie następująco:

attr Point "1024,768"

Jeśli współrzędne mają być zapisane w systemie innym niż decymalny, w parametrze AFormat podać należy odpowiednią wartość:

tsiConfig.WritePoint('First\Point', Point(1024, 768), fpOctal);

Wywołanie metody w powyższy sposób spowoduje zapisanie współrzędnych 1024 oraz 768 w systemie oktalnym do atrybutu Point, znajdującego się w węźle o nazwie First. Deklaracja atrybutu będzie wyglądać następująco:

attr Point "0o2000,0o1400"

5.8. zapis listy

Zapis zawartości listy do atrybutu umożliwia metoda WriteList, pobierająca w argumencie AAttrPath ścieżkę lub nazwę atrybutu, natomiast referencję do instancji klasy dziedziczącej z TStrings przyjmuje w parametrze AList. Każda linia listy zapisywana jest w osobnej linii wartości atrybutu.

Aby zapisać zawartość listy do atrybutu, zawartego bezpośrednio w aktualnie otwartym lub głównym węźle drzewa, w argumencie AAttrPath należy przekazać samą jego nazwę, natomiast obiekt listy podać w parametrze AList:

uses
  Classes;

{..}

var
  slValue: TStringList;

{..}

slValue := TStringList.Create();
slValue.AddStrings(['Tree', 'Structure', 'Information']);

tsiConfig.WriteList('List', slValue);

Po wykonaniu powyższej instrukcji, deklaracja atrybutu przyjmie poniższą postać:

attr List "Tree"
          "Structure"
          "Information"

Jeżeli lista składać się będzie tylko i wyłącznie z jednej pustej linii, do atrybutu zostanie wpisany pojedynczy znak o kodzie 9.

5.9. zapis dowolnego bufora danych

Do zapisu dowolnego bufora danych do atrybutu służy metoda WriteBuffer. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu, w argumencie ABuffer wskazanie na dowolny bufor danych, natomiast w parametrze ASize długość zapisywanego bufora (liczona w bajtach). Dodatkowym parametrem jest AFormat typu TFormatBuffer, który określa ilość bajtów zapisywanych w jednej linii wartości atrybutu.

Aby zapisać dowolny bufor danych w atrybucie, znajdującym się wewnątrz aktualnie otwartego lub głównego węzła drzewa, w argumencie AAttrPath należy przekazać samą nazwę atrybutu, w argumencie ABuffer podać wskazanie na bufor oraz podać jego rozmiar w parametrze ASize:

var
  strValue: String;

{..}

strValue := 'Tree Structure Information';
tsiConfig.WriteBuffer('Buffer', strValue[1], Length(strValue));

Powyższa instrukcja spowoduje zapisanie całego łańcucha znaków do atrybutu. Deklaracja atrybutu przedstawiać się będzie następująco:

attr Buffer "547265652053747275637475726520496E666F726D6174696F6E"

Metoda ta umożliwia także określenie liczby bajtów zapisywanych w każdej pojedynczej linii wartości — domyślnie są to 32 bajty, czyli 64 znaki heksadecymalne. Aby ją zmienić, w parametrze AFormat należy podać odpowiednią wartość:

tsiConfig.WriteBuffer('Buffer', strValue[1], Length(strValue), fb16BytesPerLine);

Wywołanie metody w powyższy sposób także spowoduje zapisanie całego ciągu znaków do atrybutu, jednak na każdą linię wartości przypadać będzie 16 bajtów. Deklaracja atrybutu po zapisie danych wyglądać będzie następująco:

attr Buffer "54726565205374727563747572652049"
            "6E666F726D6174696F6E"

Istnieje także możliwość zapisu fragmentu danego bufora danych. Aby tego dokonać, w parametrze ABuffer należy podać wskazanie na konkretny bajt bufora oraz określić długość zapisywanego fragmentu w argumencie ASize:

tsiConfig.WriteBuffer('First\Buffer', strValue[6], 9);

Powyższa instrukcja spowoduje zapisanie fragmentu łańcucha znaków (tu: słowa Structure) do atrybutu Buffer, zawartego wewnątrz węzła o nazwie First. Po zapisie danych, deklaracja atrybutu przedstawiać się będzie następująco:

attr Buffer "537472756374757265"

5.10. zapis strumienia danych

Do zapisu strumienia danych lub jego fragmentu do atrybutu służy metoda WriteStream. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu, w argumencie AStream referencję do obiektu klasy dziedziczącej po TStream oraz długość zapisywanego bloku w parametrze ASize. Dodatkowym parametrem jest AFormat typu TFormatBuffer, który tak samo jak w przypadku zapisu dowolnego bufora, służy do określenia długości linii wartości, liczonej w bajtach.

Aby zapisać całą zawartość strumienia do atrybutu, znajdującego się w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath podać należy samą nazwę atrybutu, w argumencie AStream przekazać obiekt strumienia oraz podać w parametrze ASize jego długość:

uses
  Classes;

{..}

var
  ssValue: TStringStream;

{..}

ssValue := TStringStream.Create('Tree Structure Information');
tsiConfig.WriteStream('Stream', ssValue, ssValue.Size);

Powyższa instrukcja spowoduje zapisanie całej zawartości strumienia, dzięki czemu deklaracja atrybutu przyjmie poniższą postać:

attr Stream "547265652053747275637475726520496E666F726D6174696F6E"

Istnieje także możliwość określenia liczby bajtów przypadających na każdą linię wartości atrybutu — domyślnie są to 32 bajty. Aby tego dokonać, w argumencie AFormat przekazać należy odpowiednią wartość:

tsiConfig.WriteStream('Stream', ssValue, ssValue.Size, fb8BytesPerLine);

Powyższa instrukcja spowoduje zapisanie także całej zawartości strumienia, jednak w każdej linii wartości atrybutu zapisanych zostanie po 8 bajtów. Deklaracja atrybutu po zapisie danych wyglądać będzie następująco:

attr Stream "5472656520537472"
            "7563747572652049"
            "6E666F726D617469"
            "6F6E"

Metoda ta umożliwia także zapis fragmentu strumienia. Aby tego dokonać, należy odpowiednio ustawić właściwość Position strumienia, tak aby wskazywał na konkretny jego bajt, natomiast w parametrze ASize podać długość fragmentu:

ssValue.Position := 16;
tsiConfig.WriteStream('First\Stream', ssValue, 11);

Metoda wywołana w powyższy sposób zapisze fragment strumienia (tu: słowa Information) do atrybutu Stream, zawartego wewnątrz węzła o identyfikatorze First. Po zapisie danych, deklaracja atrybutu przedstawiać się będzie następująco:

attr Stream "6E666F726D6174696F6E00"

6. odczytywanie danych z atrybutów

Klasa TSimpleTSInfoTree zawiera zestaw metod, umożliwiających odczyt uprzednio zapisanych danych z atrybutów. Tak samo jak w przypadku zapisu, istnieją metody do odczytu danych typów prostych, jak i zawartości klas dziedziczących z TStrings czy TStream. Odczyt danych konkretnego typu z atrybutu nie wymaga znajomości formy zapisu danych (np. systemu liczbowego, użytego do zapisu liczby) — forma ta rozpoznawana jest automatycznie.

Jeżeli atrybut, z którego odczytywane są dane nie istnieje w drzewie, nie zostaje on utworzony. Większość metod służących do odczytu danych posiada parametr z wartością domyślną, zwracaną w przypadku niepowodzenia konwersji lub nieistnienia atrybutu.

Niektóre metody wykorzystują rekord typu TFormatSettings, zawierający informacje o formatowaniu łańcuchów znaków wartości przekonwertowanych liczb zmiennoprzecinkowych, waluty oraz daty i czasu. Rekord ten może zawierać wartości pobrane z ustawień systemu lub własne, w zależności od wymagań.

6.1. odczyt wartości logicznej

Do odczytu wartości logicznej z atrybutu służy metoda ReadBoolean. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz wartość domyślną w argumencie ADefault, zwracaną w przypadku nieistnienia atrybutu lub niepowodzenia konwersji ciągu znaków wartości atrybutu na dane typu Boolean. Forma zapisu wartości logicznej w wartości atrybutu wykrywana jest automatycznie.

Poniżej deklaracja przykładowego atrybutu, zawierającego wartość logiczną zapisaną w domyślnej formie:

attr Boolean "True"

Aby odczytać wartość logiczną z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy samą jego nazwę, natomiast w parametrze ADefault podać wartość domyślną:

var
  boolValue: Boolean;

{..}

boolValue := tsiConfig.ReadBoolean('Boolean', False);

Jeżeli atrybut nie jest zawarty w aktualnie otwartym lub głównym węźle, w argumencie AAttrPath przekazać należy jego ścieżkę:

boolValue := tsiConfig.ReadBoolean('First\Boolean', False);

Powyższa instrukcja spowoduje odczytanie wartości logicznej z atrybutu Boolean, zawartego wewnątrz węzła o identyfikatorze First.

6.2. odczyt liczby całkowitej

Do odczytu liczby całkowitej z atrybutu służy metoda ReadInteger. Przyjmuje ona w parametrze AAttrPath ścieżkę lub samą nazwę atrybutu oraz wartość domyślną w argumencie ADefault, zwracaną w przypadku braku atrybutu lub niepowodzenia konwersji. System liczbowy, użyty do zapisu liczby wykrywany jest automatycznie, stąd nie jest potrzebna jego znajomość.

Poniżej deklaracja przykładowego atrybutu, zawierającego liczbę całkowitą zapisaną w domyślnej formie:

attr Integer "254"

Aby odczytać wartość liczbową z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w argumencie AAttrPath przekazać trzeba samą jego nazwę, a także określić wartość domyślną, podając ją w parametrze ADefault:

var
  intValue: Integer;

{..}

intValue := tsiConfig.ReadInteger('Integer', 0);

Natomiast jeżeli atrybut nie jest zawarty wewnątrz aktualnie otwartego lub głównego węzła, w argumencie AAttrPath podać należy jego ścieżkę:

intValue := tsiConfig.ReadInteger('First\Integer', 0);

Metoda wywołana w powyższy sposób spowoduje odczytanie liczby z atrybutu Integer, zawartego w węźle o nazwie First.

6.3. odczyt liczby zmiennoprzecinkowej

Do odczytu liczby zmiennoprzecinkowej z atrybutu służą metody ReadFloat. Przyjmują one w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz w wartość domyślną w argumencie ADefault, zwracaną w przypadku nieistnienia atrybutu lub niepowodzenia konwersji ciągu znaków wartości. Rozszerzona wersja metody umożliwia dodatkowo podanie w parametrze ASettings rekordu typu TFormatSettings, zawierającego dane regionalne, używane do konwersji natywnych danych na łańcuchy znaków.

Jeżeli do zapisu danych wykorzystywany był rekord ze zmodyfikowanymi danymi regionalnymi, rekord zawierający takie same dane musi zostać użyty do odczytu liczby. W przeciwnymi razie konwersja ciągu znaków na dane natywne nie powiedzie się.

Poniżej deklaracja przykładowego atrybutu, zawierającego liczbę zmiennoprzecinkową zapisaną w domyślnej formie:

attr Float "34,79"

Aby odczytać wartość liczbową z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w argumencie AAttrPath przekazać należy jego samą nazwę, natomiast w parametrze ADefault przekazać należy wartość domyślną:

var
  dblValue: Double;

{..}

dblValue := tsiConfig.ReadFloat('Float', 0.0);

Natomiast jeśli atrybut nie znajduje się w aktualnie otwartym lub głównym węźle, w parametrze AAttrPath przekazać należy jego ścieżkę:

dblValue := tsiConfig.ReadFloat('First\Float', 0.0);

Powyższa instrukcja spowoduje odczytanie liczby zmiennoprzecinkowej z atrybutu Float, znajdującego się w węźle o nazwie First.

6.4. odczyt waluty

Do odczytu waluty (liczby typu Currency) służą metody ReadCurrency. Przyjmują one w parametrze AAttrPath ścieżkę lub nazwę atrybutu, a także wartość domyślną w argumencie ADefault, zwracają w przypadku nieistnienia atrybutu lub niepowodzenia konwersji ciągu znaków wartości. Rozszerzona wersja metody posiada dodatkowo parametr ASettings, w którym możliwe jest podanie rekordu typu TFormatSettings, zawierającego dane regionalne, używane do formatowania łańcuchów znaków.

Jeżeli do zapisu danych wykorzystywany był rekord ze zmodyfikowanymi danymi regionalnymi, rekord zawierający takie same dane musi zostać użyty do odczytu kwoty. W przeciwnymi razie konwersja łańcucha znaków na dane natywne nie powiedzie się.

Poniżej przykładowa deklaracja atrybutu zawierającego kwotę, zapisaną w domyślnej formie:

attr Currency "12,43 zł"

Aby odczytać kwotę z powyższego atrybutu, w przypadku gdy zawarty on jest w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy samą jego nazwę, natomiast w argumencie ADefault należy określić wartość domyślną:

var
  currValue: Currency;

{..}

currValue := tsiConfig.ReadCurrency('Currency', 0.0);

Jeżeli nazwa waluty zawiera znaki, które w kodowaniu UTF-8 są multibajtowe, podczas gdy domyślnie nazwa ta kodowana jest w ANSI, należy skorzystać z procedury GetLocaleFormatSettings w celu pobrania danych regionalnych, a następnie wpisać ciąg znaków kodowany w UTF-8 do pola CurrencyString rekordu. Dzięki temu konwersja łańcucha znaków wartości na dane natywne przebiegnie pomyślnie:

uses
  SysUtils;

{..}

var
  fsPolish: TFormatSettings;

{..}

GetLocaleFormatSettings(1045, fsPolish);
fsPolish.CurrencyString := 'zł';

currValue := tsiConfig.ReadCurrency('Currency', 0.0, fsPolish);

Jeżeli atrybut nie znajduje się w aktualnie otwartym lub głównym węźle, w parametrze AAttrPath przekazać należy jego pełną ścieżkę:

currValue := tsiConfig.ReadCurrency('First\Currency', 0.0, fsPolish);

Metoda wywołana w powyższy sposób spowoduje odczytanie kwoty z atrybutu Currency, znajdującego się w węźle o nazwie First.

6.5. odczyt łańcucha znaków

Do odczytu pojedynczego łańcucha znaków z atrybutu służy metoda ReadString. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz w argumencie ADefault domyślny ciąg znaków, zwracany tylko i wyłącznie w przypadku nieistnienia atrybutu. Dodatkowym parametrem jest AFormat typu TFormatString, który służy do określenia wielkości znaków odczytywanego z atrybutu ciągu znaków.

Poniżej deklaracja przykładowego atrybutu, zawierającego jednoliniowy ciąg znaków:

attr String "Tree Structure Information"

Aby odczytać łańcuch znaków z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy sam jego identyfikator, a także należy określić wartość domyślną w argumencie ADefault:

var
  strValue: String;

{..}

strValue := tsiConfig.ReadString('String', '');

Jeżeli atrybut nie znajduje się w aktualnie otwartym lub głównym węźle, w argumencie AAttrPath podać należy jego pełną ścieżkę. Natomiast aby zmienić wielkość znaków odczytywanego łańcucha, w parametrze AFormat przekazać należy odpowiednią wartość:

strValue := tsiConfig.ReadString('First\String', '', fsLowerCase);

Metoda wywołana w powyższy sposób spowoduje odczytanie i zwrócenie ciągu znaków tree structure information pobranego z atrybutu String, zawartego w węźle o nazwie First.

Poniżej przykład deklaracji atrybutu zawierającego wieloliniowy łańcuch znaków:

attr String "Tree"
            "Structure"
            "Information"

Bezpośredni odczyt wartości spowoduje zwrócenie przez metodę ciągu znaków, w którym poszczególne linie rozdzielone są znakami o kodzie 10. Aby domyślne znaki separatora zamienić na własne znaki lub ciągi znaków, po odczycie danych z atrybutu należy je zamienić np. za pomocą funkcji ReplaceSubStrings:

uses
  TSInfoUtils, TSInfoConsts;

{..}

strValue := ReplaceSubStrings(tsiConfig.ReadString('String', ''), VALUES_DELIMITER, '|');

Wywołanie metody w powyższy sposób spowoduje odczyt łańcucha znaków z atrybutu String, znajdującego się w aktualnie otwartym lub głównym węźle drzewa. Do zmiennej zostanie wpisany ciąg znaków Tree|Structure|Information, w którym znaki domyślnego separatora wartości zostały zamienione na znaki |.

6.6. odczyt daty i czasu

Do odczytu daty i czasu z atrybutu służą metody ReadDateTime. Pobierają one w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz wartość domyślną w parametrze ADefault, zwracaną w przypadku niepowodzenia konwersji lub nieistnienia atrybutu. Dodatkowym parametrem jest ASettings — umożliwia on przekazanie rekordu typu TFormatSettings, zawierającego własnoręcznie zdefiniowane dane regionalne.

Zapis i odczyt wartości daty i czasu do i z jednego atrybutu musi być przeprowadzony na dokładnie takim samym łańcuchu maski.
Jeżeli do zapisu danych wykorzystywany był rekord ze zmodyfikowanymi danymi regionalnymi, rekord zawierający takie same dane musi zostać użyty do odczytu daty i czasu. W przeciwnymi razie konwersja łańcucha znaków na dane natywne nie powiedzie się.

Poniżej deklaracja atrybutu zawierającego wartość daty i czasu, zapisanej za pomocą prostej maski D.MM.YYYY, H:NN:SS:

attr DateTime "21-11-2015, 3:13:32"

Aby odczytać datę i czas z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy samą nazwę atrybutu, natomiast w parametrze ADefault należy określić wartość domyślną:

var
  dtValue: TDateTime;

{..}

dtValue := tsiConfig.ReadDateTime('DateTime', 'D.MM.YYYY, H:NN:SS', 0);

Jeżeli atrybut nie znajduje się wewnątrz aktualnie otwartego lub głównego węzła, w argumencie AAttrPath podać należy jego pełną ścieżkę:

dtValue := tsiConfig.ReadDateTime('First\DateTime', 'D.MM.YYYY, H:NN:SS', 0);

Wywołanie metody w powyższy sposób spowoduje odczytanie wartości daty i czasu z atrybutu DateTime, znajdującego się bezpośrednio w węźle o nazwie First. W przypadku braku atrybutu lub niepowodzenia konwersji, metoda zwróci wartość 0, w tym przypadku będzie to odpowiednik daty 30.12.1899 oraz czasu 0:00:00:000.

6.7. odczyt współrzędnych punktu

Odczyt współrzędnych punktu z atrybutu możliwy jest za pomocą metody ReadPoint. Przyjmuje ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz wartość domyślną w argumencie ADefault, zwracaną w przypadku niepowodzenia konwersji łańcucha wartości na dane natywne lub braku atrybutu. System liczbowy, w którym zapisane są składowe w wartości atrybutu rozpoznawany jest automatycznie, stąd niepotrzebna jest jego znajomość.

Poniżej przykład deklaracji atrybutu zawierającego współrzędne punktu, zapisane w domyślnym systemie liczbowym:

attr Point "1024,768"

Aby odczytać współrzędne z powyższego atrybutu, w przypadku gdy atrybut znajduje się wewnątrz aktualnie otwartego lub głównego węzła drzewa, w argumencie AAttrPath przekazać należy jego samą nazwę, natomiast w parametrze ADefault określić wartość domyślną:

uses
  Types;

{..}

var
  ptValue: TPoint;

{..}

ptValue := tsiConfig.ReadPoint('Point', Point(0, 0));

Jeżeli atrybut nie znajduje się wewnątrz aktualnie otwartego lub głównego węzła, w parametrze AAttrPath przekazać należy jego ścieżkę:

ptValue := tsiConfig.ReadPoint('First\Point', Point(0, 0));

Wywołanie metody w powyższy sposób spowoduje odczytanie współrzędnych punktu z atrybutu Point, znajdującego się w węźle o identyfikatorze First. Jeżeli konwersja nie powiedzie się lub atrybut nie istnieje, metoda zwróci współrzędne o wartościach 0 i 0.

6.8. odczyt listy

Do odczytu listy ciągów znaków z atrybutu służy metoda ReadList, pobierająca w parametrze AAttrPath ścieżkę lub nazwę atrybutu oraz referencję do obiektu klasy dziedziczącej z TStrings w argumencie AList. Metoda ta nie ingeruje w bieżącą zawartość listy, a jedynie dodaje na jej koniec ciągi znaków, odczytane z atrybutu.

Poniżej deklaracja atrybutu zawierającego wieloliniową wartość:

attr List "Tree"
          "Structure"
          "Information"

Aby odczytać dane z powyższego atrybutu, w przypadku gdy zawarty jest on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy sam identyfikator atrybutu, natomiast obiekt utworzonej w pamięci listy podać w argumencie AList:

uses
  Classes;

{..}

var
  slValue: TStringList;

{..}

slValue := TStringList.Create();
tsiConfig.ReadList('List', slValue);

Jeśli atrybut nie znajduje się w aktualnie otwartym lub głównym węźle, w parametrze AAttrPath podać należy jego ścieżkę:

tsiConfig.ReadList('First\List', slValue);

Powyższa instrukcja spowoduje odczytanie listy ciągów znaków z atrybutu List, znajdującego się w węźle o nazwie First. Jeżeli atrybut o podanej ścieżce lub nazwie nie istnieje w drzewie lub jeśli zawiera pustą wartość, zawartość listy nie ulegnie zmianie.

6.9. odczyt dowolnego bufora danych

Do odczytu dowolnego bufora danych z atrybutu służy metoda ReadBuffer. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu, w argumencie ABuffer wskazanie na docelowy bufor danych oraz w parametrze ASize liczbę odczytywanych bajtów. Dodatkowo, istnieje możliwość określenia w parametrze AOffset numeru bajtu, od którego rozpocznie się wczytywanie. Dzięki temu możliwe jest odczytanie zadanego fragmentu bufora, zapisanego w atrybucie.

Aby móc prawidłowo odczytać całą zawartość zapisanego w atrybucie bufora, konieczna jest znajomość jego długości.

Poniżej deklaracja przykładowego atrybutu, zawierającego zapis bufora danych w domyślnej formie:

attr Buffer "547265652053747275637475726520496E666F726D6174696F6E"

Aby odczytać całą zawartość bufora z powyższego atrybutu, w przypadku gdy znajduje się on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy jego samą nazwę, natomiast w argumencie ABuffer podać należy wskazanie na bufor docelowy oraz w parametrze ASize przekazać zapamiętaną lub znaną jego długość:

var
  strValue: String;

{..}

SetLength(strValue, 26);
tsiConfig.ReadBuffer('Buffer', strValue[1], 26);

Aby odczytać bufor z atrybutu, który nie znajduje się w aktualnie otwartym lub głównym węźle, w parametrze AAttrPath podać należy jego ścieżkę:

tsiConfig.ReadBuffer('First\Buffer', strValue[1], 26);

Metoda wywołana w powyższy sposób spowoduje odczytanie całego bufora danych z atrybutu Buffer, zawartego bezpośrednio w węźle o identyfikatorze First. Istnieje także możliwość pobrania fragmentu bufora. Aby tego dokonać, w parametrze AOffset podać należy numer bajtu, od którego rozpocznie się odczyt danych (bajty indeksowane są od 0):

SetLength(strValue, 9);
tsiConfig.ReadBuffer('Buffer', strValue[1], 9, 5);

Metoda wywołana w powyższy sposób spowoduje odczytanie fragmentu bufora z atrybutu o nazwie Buffer, znajdującego się w aktualnie otwartym lub głównym węźle drzewa. Odczyt rozpocznie się od szóstego bajtu (o indeksie 5) oraz obejmie odczyt dziewięciu bajtów, dlatego też do zmiennej zostanie wczytane słowo Structure.

6.10. odczyt strumienia danych

Do odczytu strumienia danych z atrybutu służy metoda ReadStream. Pobiera ona w parametrze AAttrPath ścieżkę lub nazwę atrybutu, w argumencie AStream przyjmuje referencję do obiektu klasy dziedziczącej z TStream, a także liczbę odczytywanych bajtów w parametrze ASize. Tak samo jak w przypadku odczytu dowolnego bufora danych, możliwe jest określenie w parametrze AOffset numeru bajtu, od którego rozpocznie się odczyt fragmentu zapisanego w atrybucie strumienia.

Aby móc prawidłowo odczytać całą zawartość zapisanego w atrybucie strumienia, konieczna jest znajomość jego długości.

Poniżej deklaracja atrybutu, zawierającego zapis strumienia danych w domyślnej formie:

attr Stream "547265652053747275637475726520496E666F726D6174696F6E"

Aby odczytać całą zawartość strumienia z powyższego atrybutu, w przypadku gdy zawarty jest on w aktualnie otwartym lub głównym węźle drzewa, w parametrze AAttrPath przekazać należy samą jego nazwę, natomiast w parametrze AStream podać należy obiekt strumienia oraz określić liczbę wczytywanych bajtów w argumencie ASize:

uses
  Classes;

{..}

var
  ssValue: TStringStream;

{..}

ssValue := TStringStream.Create('');
tsiConfig.ReadStream('Stream', ssValue, 26);

Jeżeli atrybut nie znajduje się w aktualnie otwartym lub głównym węźle, w parametrze AAttrPath przekazać należy jego ścieżkę:

tsiConfig.ReadStream('First\Stream', ssValue, 26);

Metoda wywołana w powyższy sposób spowoduje odczytanie całego strumienia z atrybutu Stream, zawartego w węźle o nazwie First. Istnieje także możliwość odczytania wybranego fragmentu strumienia. Aby tego dokonać, w argumencie AOffset przekazać należy numer bajtu, od którego rozpocznie się wczytywanie danych (bajty indeksowane są od 0):

tsiConfig.ReadStream('Stream', ssValue, 11, 15);

Tak wywołana metoda spowoduje odczytanie fragmentu strumienia z atrybutu o nazwie Stream, znajdującego się w aktualnie otwartym lub głównym węźle drzewa. Odczyt rozpocznie się od szesnastego bajtu (o indeksie 15) oraz obejmie odczyt jedenastu bajtów, dlatego też do strumienia wpisany zostanie ciąg znaków Information.

7. tworzenie nowych elementów drzewa

Podstawowa klasa do obsługi plików TreeStructInfo umożliwia tworzenie pustych elementów drzewa, takich jak standardowe oraz referencjonowane atrybuty oraz węzły potomne. Podczas tworzenia elementu, możliwe jest określenie (oprócz jego identyfikatora) jego stanu referencjonowania.

Jeżeli przed utworzeniem elementu w drzewie, dowolny węzeł został otwarty za pomocą metody OpenChildNode, wyszukiwanie wskazanego węzła-rodzica nie rozpocznie się od głównego węzła głównego drzewa, a od tego aktualnie otwartego.

Metody służące do utworzenia nowego elementu przyjmują w parametrze przede wszystkim ścieżkę lub nazwę węzła-rodzica, w którym mają zostać utworzone, ale także unikalny identyfikator oraz stan referencjonowania. Dostępne są także opcjonalne parametry, umożliwiające podanie dodatkowych informacji lub wartości sterujących klasą drzewa.

Metody te nie sprawdzają, czy element o wskazanej nazwie istnieje bezpośrednio w danym węźle-rodzicu.

7.1. tworzenie nowego atrybutu

Do utworzenia atrybutu w zadanym węźle służy metoda CreateAttribute. Pobiera ona w parametrze ANodePath ścieżkę lub nazwę węzła rodzica, w którym zostanie utworzony atrybut, a także stan referencjonowania tworzonego atrybutu w argumencie AReference oraz jego identyfikator w parametrze AAttrName.

Aby utworzyć standardowy atrybut bezpośrednio w aktualnie otwartym lub głównym węźle drzewa, należy przekazać w parametrze ANodePath pusty łańcuch lub specjalny symbol (znak ~), natomiast w parametrze AReference określić jego stan referencjonowania oraz jego nazwę w argumencie AAttrName:

tsiConfig.CreateAttribute('~', False, 'New');

Jeśli atrybut nie ma być dodany do aktualnie otwartego lub głównego węzła, w parametrze ANodePath podać należy ścieżkę węzła-rodzica. Aby utworzyć atrybut referencjonowany, w argumencie AReference przekazać należy wartość True:

tsiConfig.CreateAttribute('First\Second\', False, 'New');

Wywołanie metody w powyższy sposób spowoduje utworzenie atrybutu o identyfikatorze New wewnątrz węzła o nazwie Second, który zawarty jest w węźle First. W przypadku gdy węzeł-rodzic nie istnieje w drzewie, pełna ścieżka węzłów zostanie utworzona.

7.2. tworzenie nowego węzła potomnego

Do utworzenia nowego węzła potomnego w drzewie służy metoda CreateChildNode. Pobiera ona w parametrze ANodePath ścieżkę lub nazwę węzła-rodzica, w którym zostanie utworzony zadany węzeł potomny, a także stan referencjonowania w parametrze AReference oraz unikalny identyfikator w argumencie ANodeName. Metoda ta posiada także opcjonalny parametr AOpen, umożliwiający otwarcie węzła potomnego, tuż po jego utworzeniu w strukturze drzewa.

Aby utworzyć standardowy węzeł potomny bezpośrednio w aktualnie otwartym lub głównym węźle drzewa, w parametrze ANodePath podać należy pusty ciąg znaków lub specjalny symbol (znak ~), natomiast w argumencie AReference określić jego stan referencjonowania oraz jego nazwę w parametrze ANodeName:

tsiConfig.CreateChildNode('~', False, 'New');

Jeżeli nowy węzeł potomny nie ma być utworzony w aktualnie otwartym lub głównym węźle, w argumencie ANodePath przekazać należy jego ścieżkę. Aby utworzyć referencjonowany węzeł potomny, w argumencie AReference podać należy wartość True:

tsiConfig.CreateChildNode('First\Second\', True, 'New');

Metoda wywołana w powyższy sposób spowoduje utworzenie referencjonowanego węzła o nazwie New wewnątrz węzła Second, który z kolei zawarty jest w węźle o identyfikatorze First. W przypadku gdy węzeł-rodzic nie istnieje w drzewie, pełna ścieżka węzłów zostanie utworzona.

Istnieje także możliwość automatycznego otwarcia węzła, tuż po jego utworzeniu w drzewie. Aby tego dokonać, w parametrze AOpen należy podać wartość True:

tsiConfig.CreateChildNode('First\Second\', True, 'New', True);

Po wykonaniu powyższej instrukcji, właściwość CurrentlyOpenNodePath będzie zwracać ścieżkę First\Second\New\.

8. usuwanie całej zawartości

Podstawowa klasa do obsługi plików TreeStructInfo zawiera metody umożliwiające usuwanie całej zawartości, czyli wszystkich standardowych oraz referencjonowanych atrybutów i węzłów potomnych, znajdujących się w danym węźle. Co za tym idzie, służą do usuwania całych gałęzi drzewa.

Metody mogą tworzyć wyjątki klasy ETSInfoFileException, jeżeli próba usunięcia zawartości wskazanego węzła lub całej zawartości drzewa konfiguracji wykonywana jest w momencie, gdy włączony jest tryb węzła otwartego tylko do odczytu.

8.1. usuwanie całej zawartości węzła

Do usunięcia całej zawartości wskazanego węzła służy metoda ClearChildNode. Pobiera ona w parametrze ANodePath ścieżkę lub nazwę węzła, którego zawartość ma zostać usunięta. Domyślna wartość tego parametru to symbol ~, który oznacza usunięcie zawartości aktualnie otwartego lub głównego węzła drzewa. Możliwe jest także podanie samej nazwy lub ścieżki węzła potomnego.

Poniżej zawartość przykładowego węzła potomnego:

node Second
  attr Foo "Value"
  attr Bar "Value"
  node Third
    attr Bald "Value"
  end node
end node

Aby usunąć zawartość powyższego węzła, w przypadku gdy jest on aktualnie otwarty, w parametrze ANodePath podać należy pusty łańcuch znaków lub specjalny symbol (znak ~), albo też użyć domyślnej jego wartości:

tsiConfig.ClearChildNode();

Jeśli węzeł ten nie jest aktualnie otwarty, w argumencie ANodePath podać należy jego nazwę lub ścieżkę:

tsiConfig.ClearChildNode('First\Second\');

Metoda wywołana w powyższy sposób spowoduje usunięcie wszystkich atrybutów i węzłów potomnych, zawartych wewnątrz węzła Second, który z kolei znajduje się w węźle o nazwie First. Jeżeli węzeł Second także ma zostać usunięty z drzewa, należy użyć metody usuwającej pojedynczy węzeł, czyli metody RemoveChildNode z klasy rozszerzonej.

8.2. usuwanie całej zawartości drzewa

Usunięcie całej zawartości drzewa umożliwia metoda ClearTree. Usuwa z drzewa wszystkie standardowe i referencjonowane atrybuty oraz węzły potomne. Aby usunąć całą zawartość drzewa, tryb węzła otwartego tylko do odczytu nie może być włączony.

9. tokenizowanie elementów drzewa

Tokenizowanie elementów drzewa polega na ich wyszukiwaniu w danym węźle głównym lub potomnym, bez konieczności odwoływania się do elementów za pomocą standardowych ścieżek dostępu. Dzięki temu możliwe jest wygodniejsze pobieranie informacji z wszystkich elementów jednego typu, bądź też ich modyfikowanie. Metody bazowej klasy TSimpleTSInfoTree umożliwiają przeglądanie atrybutów oraz węzłów potomnych. Samo tokenizowanie może być jednopoziomowe lub wielopoziomowe i nie jest zależne od stanu referencjonowania elementów.

Brak konieczności odwoływania się do elementów drzew na podstawie ich nazw lub ścieżek nie zwalnia z konieczności używania unikalnych identyfikatorów. W dalszym ciągu elementy jednego typu, zawarte bezpośrednio w danym węźle nie mogą posiadać identycznych nazw i od tej reguły nie ma odstępstw.

W procesach tokenizowania elementów wykorzystywane są dwa typy obiektów — TTSInfoAttributeToken oraz TTSInfoChildNodeToken. Pozwalają na bezpośredni dostęp do składowych klas elementów, nie udostępniając referencji do ich obiektów. Obiekty tokenów umożliwiają modyfikację wszystkich danych elementów, takich jak identyfikatory, stany referencjonowania oraz komentarze (w przypadku atrybutów także ich wartości).

9.1. tokenizowanie atrybutów

Do tokenizowania atrybutów służą dwie metody. FindFirstAttribute umożliwia wyszukanie pierwszego atrybutu, pobierając obiekt tokenu typu TTSinfoAttributeToken w parametrze AAttrToken oraz ścieżkę lub nazwę węzła-rodzica w parametrze AParentNodePath, w którym atrybuty będą wyszukiwane. Do wyszukiwania kolejnych atrybutów służy metoda FindNextAttribute, pobierająca w argumencie AAttrToken wskazanie na obiekt uprzednio uzupełnionego tokenu.

Wyżej wymienionych metod należy używać nierozłącznie, według poniższego schematu:

var
  attrToken: TTSInfoAttributeToken;

{..}

if tsiConfig.FindFirstAttribute(attrToken, 'First\Second\') then
repeat
  { wykorzystanie tokenu znalezionego atrybutu }
until not tsiConfig.FindNextAttribute(attrToken);

Powyższy przykład pokazuje sposób na przeglądnięcie wszystkich atrybutów, zawartych w węźle Second, który z kolei znajduje się wewnątrz węzła o identyfikatorze First. Jeżeli wyszukane mają być atrybuty, zawarte wewnątrz aktualnie otwartego lub głównego węzła drzewa, w parametrze AParentNodePath metody FindFirstAttribute przekazać należy pusty ciąg znaków, symbol ~ lub użyć wartości domyślnej:

if tsiConfig.FindFirstAttribute(attrToken, '~') then
repeat
  { wykorzystanie tokenu znalezionego atrybutu }
until not tsiConfig.FindNextAttribute(attrToken);

Możliwe jest także tokenizowanie atrybutów w połączeniu z metodą OpenChildNode:

if tsiConfig.OpenChildNode('First\Second\') then
try
  if tsiConfig.FindFirstAttribute(attrToken) then
  repeat
    { wykorzystanie tokenu znalezionego atrybutu }
  until not tsiConfig.FindNextAttribute(attrToken);
finally
  tsiConfig.CloseChildNode();
end;

Powyższy kod zrealizuje najpierw otwarcie zadanego węzła-rodzica, następnie już bez podawania ścieżki węzła, wyszuka pierwszy i kolejne atrybuty, znajdujące się w aktualnie otwartym węźle. Proces wyszukiwania atrybutów nie zostanie zrealizowany, jeżeli węzeł o ścieżce First\Second\ nie istnieje w strukturze drzewa lub jeśli węzeł ten nie zawiera atrybutów.

9.2. tokenizowanie węzłów potomnych

Do tokenizowania węzłów potomnych służą dwie metody. FindFirstChildNode umożliwia wyszukanie pierwszego węzła potomnego, pobierając obiekt tokenu typu TTSInfoChildNodeToken w argumencie ANodeToken oraz ścieżkę lub nazwę węzła-rodzica w parametrze AParentNodePath, w którym węzły potomne będą wyszukiwane. Do wyszukiwania kolejnych węzłów potomnych służy metoda FindNextChildNode, przyjmująca w parametrze ANodeToken obiekt uprzednio uzupełnionego tokenu.

Wyżej wymienionych metod należy używać nierozłącznie, według poniższego schematu:

var
  nodeToken: TTSInfoChildNodeToken;

{..}

if tsiConfig.FindFirstChildNode(nodeToken, 'First\Second\') then
repeat
  { wykorzystanie tokenu znalezionego węzła potomnego }
until not tsiConfig.FindNextChildNode(nodeToken);

Powyższy przykład demonstruje sposób na przeglądnięcie wszystkich węzłów potomnych, zawartych bezpośrednio w węźle Second, który z kolei znajduje się wewnątrz węzła o nazwie First. Jeżeli mają być wyszukane węzły potomne, zawarte wewnątrz aktualnie otwartego lub głównego węzła drzewa, w parametrze AParentNodePath metody FindFirstChildNode podać należy pusty ciąg znaków, symbol ~ lub wykorzystać wartość domyślną:

if tsiConfig.FindFirstChildNode(nodeToken, '~') then
repeat
  { wykorzystanie tokenu znalezionego węzła potomnego }
until not tsiConfig.FindNextChildNode(nodeToken);

Możliwe jest także tokenizowanie węzłów potomnych w połączeniu z metodą OpenChildNode:

if tsiConfig.OpenChildNode('First\Second\') then
try
  if tsiConfig.FindFirstChildNode(nodeToken) then
  repeat
    { wykorzystanie tokenu znalezionego węzła potomnego }
  until not tsiConfig.FindNextChildNode(nodeToken);
finally
  tsiConfig.CloseChildNode();
end;

Powyższy kod umożliwi najpierw otwarcie zadanego węzła-rodzica, następnie już bez podawania ścieżki, wyszuka pierwszy i kolejne węzły potomne, znajdujące się w aktualnie otwartym węźle. Proces wyszukiwania węzłów potomnych nie zostanie zrealizowany, jeżeli węzeł o ścieżce First\Second\ nie istnieje w drzewie lub jeśli nie zawiera on węzłów potomnych.

10. masowe zmiany nazw elementów

Bazowa klasa zawiera dwie metody, służące do masowej zmiany nazw elementów jednego typu — atrybutów lub węzłów potomnych. Proces zmiany identyfikatorów wszystkich elementów opiera się na ścieżce lub nazwie węzła-rodzica, zawierającego elementy do zmiany nazw, a także na podstawie specjalnego łańcucha maski, stanowiącego wzorzec identyfikatora. Wszystkie elementy otrzymają nowe identyfikatory według tego wzorca, a odróżniać je będzie nadawany numer, wstawiany w określone przez podciąg %d miejsce w łańcuchu znaków maski.

Podciąg %d może istnieć tylko i wyłącznie w jednym miejscu łańcucha znaków maski, a samo jego istnienie jest obowiązkowe.

Metody zmieniające masowo nazwy elementów umożliwiają podanie liczby, stanowiącej numer pierwszego elementu, a także kierunek zmiany wartości tego numeru jako wartość typu TRenamingDirection. Dzięki temu kolejne elementy otrzymywać będą nowy identyfikator z większym lub mniejszym numerem.

Proces masowej zmiany nazw wykorzystuje standardowy mechanizm tokenizowania elementów, dlatego że ich obecne nazwy nie są znane.

10.1. zmiana nazw wszystkich atrybutów

Do zmiany nazw wszystkich atrybutów służy metoda RenameAttributeTokens. Pobiera ona w parametrze ANodePath ścieżkę lub nazwę węzła, w którym znajdują się elementy do zmiany identyfikatorów, ciąg znaków maski w argumencie ATokenName, początkowy numer w parametrze AStartIndex oraz kierunek zmiany wartości numeru w parametrze ADirection typu TRenamingDirection.

Poniżej przykład zawartości standardowego węzła potomnego:

node Second
  attr Foo "Value"
  attr Bald "Value"
  attr Bar "Value"
end node

Aby zmienić nazwy wszystkich atrybutów zawartych w powyższym węźle, w przypadku gdy jest on aktualnie otwarty, w parametrze ANodePath przekazać należy pusty ciąg znaków lub specjalny symbol (znak ~):

tsiConfig.RenameAttributeTokens('~', 'Name %d', 0, rdAscending);

Metoda wywołana w powyższy sposób spowoduje zmianę nazw wszystkich atrybutów znajdujących się wewnątrz aktualnie otwartego węzła, gdzie pierwszy atrybut otrzyma numer 0, a kolejne o jeden większy od poprzedniego. Po wywołaniu metody, zawartość węzła przedstawiać się będzie następująco:

node Second
  attr Name 0 "Value"
  attr Name 1 "Value"
  attr Name 2 "Value"
end node

Jeżeli zmiana identyfikatorów atrybutów ma zostać przeprowadzona na węźle, który nie jest aktualnie otwarty, w argumencie ANodePath podać należy jego nazwę lub ścieżkę:

tsiConfig.RenameAttributeTokens('First\Second\', 'Name %d', 100, rdDescending);

Wywołanie metody w powyższy sposób spowoduje zmianę nazw atrybutów zawartych w węźle Second, który zawarty jest wewnątrz węzła o nazwie First. Pierwszy atrybut otrzyma numer 100, a kolejne o jeden mniejszy od poprzedniego. Po wykonaniu kodu, zawartość węzła przyjmie poniższą postać:

node Second
  attr Name 100 "Value"
  attr Name 99 "Value"
  attr Name 98 "Value"
end node

Aby identyfikatory składały się tylko i wyłącznie z numerów porządkowych, w parametrze ATokenName przekazać należy ciąg znaków %d.

10.2. zmiana nazw wszystkich węzłów potomnych

Do zmiany nazw wszystkich węzłów potomnych służy metoda RenameChildNodeTokens. Pobiera w parametrze ANodePath ścieżkę lub nazwę węzła, w którym znajdują się węzły potomne do zmiany identyfikatorów, łańcuch znaków maski w argumencie ATokenName, początkowy numer w parametrze AStartIndex oraz kierunek zmiany wartości numeru w argumencie ADirection typu TRenamingDirection.

Poniżej przykład zawartości standardowego węzła potomnego:

node Second
  node Foo
  end node
  node Bald
  end node
  node Bar
  end node
end node

Aby zmienić nazwy wszystkich węzłów potomnych zawartych w powyższym węźle, w przypadku gdy jest on aktualnie otwarty, w parametrze ANodePath przekazać należy pusty ciąg znaków lub specjalny symbol (znak ~):

tsiConfig.RenameChildNodeTokens('~', 'Name %d', 0, rdAscending);

Powyższy kod spowoduje zmianę identyfikatorów wszystkich węzłów potomnych, znajdujących się bezpośrednio w aktualnie otwartym węźle, gdzie pierwszy węzeł potomny otrzyma numer 0, a kolejne o jeden większy od poprzedniego. Po wywołaniu metody, zawartość węzła wyglądać będzie następująco:

node Second
  node Name 0
  end node
  node Name 1
  end node
  node Name 2
  end node
end node

Jeśli zmiana nazw węzłów potomnych ma zostać przeprowadzona w węźle, który nie jest aktualnie otwarty, w argumencie ANodePath przekazać należy jego nazwę lub ścieżkę:

tsiConfig.RenameChildNodeTokens('First\Second\', 'Name %d', 100, rdDescending);

Metoda wywołana w powyższy sposób spowoduje zmianę nazw węzłów potomnych zawartych w węźle o nazwie Second, który z kolei znajduje się wewnątrz węzła First. Pierwszy węzeł potomny otrzyma numer 100, a kolejne o jeden mniejszy od poprzedniego. Po wywołaniu metody, zawartość węzła przedstawiać się będzie następująco:

node Second
  node Name 100
  end node
  node Name 99
  end node
  node Name 98
  end node
end node

Aby identyfikatory składały się tylko i wyłącznie z numerów porządkowych, w argumencie ATokenName podać należy łańcuch %d.

11. aktualizowanie pliku źródłowego

Do zaktualizowania pliku źródłowego lub jego utworzenia służy metoda UpdateFile. Metoda ta określa formę pliku docelowego na podstawie trybu tmBinaryTree. Jeżeli tryb ten istnieje w zbiorze, drzewo zostanie zapisane do pliku w formie binarnej, w przeciwnym razie w formie tekstowej. Wywołanie tej metody możliwe jest także w przypadku, gdy drzewo zostało załadowane w trybie tylko do odczytu.

Aby możliwy był zapis drzewa z pamięci do pliku dyskowego, pole zawierające nazwę lub ścieżkę pliku nie może być puste.

12. zmiana docelowej formy drzewa

Do zmiany docelowej formy drzewa służy bezparametrowa metoda SwitchTreeForm. Jeżeli drzewo zostało załadowane z danego źródła z wykorzystaniem trybu tmTextTree, zostanie on usunięty i zastąpiony wartością tmBinaryTree. Ponowne wywołanie tej metody odwraca proces.

Zmiana formy drzewa załadowanego w trybie tylko do odczytu, nie daje żadnych rezultatów.

13. zmiana trybu użytkowania drzewa

Aby zmienić tryb użytkowania drzewa, należy skorzystać z metody SwitchTreeAccess. Jeśli drzewo zostało załadowane jedynie do odczytu (z użyciem trybu tmAccessRead), wywołanie tej metody spowoduje zastąpienie wymienionego trybu wartością tmAccessWrite, co umożliwi automatyczny zapis drzewa z pamięci do pliku, w destruktorze klasy drzewa.

Metoda ta umożliwia także działanie odwrotne — jeśli drzewo zostało utworzone lub załadowane w trybie do odczytu i zapisu, flaga tmAccessWrite zostanie zastąpiona enumem tmAccessRead, wykluczając automatyczny zapis drzewa w destruktorze.

Zobacz też:

copyright © furious programming 2013—2018