TreeStructInfo - format tekstowych i binarnych plików konfiguracyjnych

0

jaka jest jedna zaleta tego formatu ktorej nie ma YAML?

Np. forma binarna, znacznie przyspieszająca ładowanie i zapis z i do plików, możliwa do łatwej konwersji na formę tekstową - w 100% kompatybilna z tekstową; Inny przykład to linki do plików dołączanych (tekstowych bądź binarnych), dających możliwość zbudowania "systemu konfiguracji", mogącego składać się z dowolnej liczby plików; Ładujesz głowny plik, a linki pozwalają automatycznie dowiązać drzewa z innych plików do głównego; I na pewno elementy referencjonowane, wydzielone z głównego ciała drzewa; A jeśli takie elementy to i wspomnieć trzeba o możliwości wielopoziomowego referencjonowania;

Nie znam zbyt dobrze szczegółów i szczególików formatu YAML, ale te powyższe wystarczą jako odpowiedź na Twoje pytanie;

ostatnio stanalem przed koniecznoscia wyboru formatu configow w jednym projekcie, dla beki rozwazylem tez treestructinfo

Piszesz we Free Pascalu? Bo jeśli nie, to "dla beki" rozważ rejestr systemu.

1
furious programming napisał(a):

Np. forma binarna, znacznie przyspieszająca ładowanie i zapis z i do plików, możliwa do łatwej konwersji na formę tekstową - w 100% kompatybilna z tekstową

forma binarna do configow? :DDDDDDDDDDDDDDDDDDDD

furious programming napisał(a):

Inny przykład to linki do plików dołączanych (tekstowych bądź binarnych), dających możliwość zbudowania "systemu konfiguracji", mogącego składać się z dowolnej liczby plików

format plikow konfiguracyjnych jest od realizowania logiki???

  1. mam hosting shellowy i kazdy user se moze skonfigurowac vhosta w httpd za pomoca specjalnego konfigu ktory umieszcza w ~
  2. obserwuje katalogi userow czy sie nic nie zmienilo/nie pojawilo
  3. jak sie zmienilo to wczytuje konfig do programu, interpretuje go i zamieniam w konfig zrozumialy dla apacza (po walidacji czy user uzywa dobrych dyrektyw, czy uzywa domen i portow ktorych mu wolno uzywac itp.)
  4. user mi gdzies wpieprza "include "/root/costam" i robi mi injecta :O

genialny pomysl, w yamlu ani w jsonie nie ma takiego pseudoficzera cale szczescie, a jak ktos potrzebuje to moze sobie doimplementowac, ustalajac sztywno swoje zasady dzialania takiej dyrektywy (czy to na poziomie danych, czy na poziomie formatu, lepiej i tak na poziomie danych)

furious programming napisał(a):

elementy referencjonowane, wydzielone z głównego ciała drzewa; A jeśli takie elementy to i wspomnieć trzeba o możliwości wielopoziomowego referencjonowania

a bo niby w yamlu sie nie da?

https://gist.github.com/bowsersenior/979804#file-stooges-yml

4

forma binarna do configow? :DDDDDDDDDDDDDDDDDDDD

Naprawdę nie widziałeś nigdy binarnego pliku z przeróżnymi danymi konfiguracyjnymi? Ja widziałem dużo np. w grach czy aplikacjach desktopowych; Zresztą binarna forma TSI tak samo zawiera dane w postaci łańcuchów, ale same dane atrybutów; Nie posiada natomiast zbędnych danych takich jak wcięcia czy puste linie, a elementy referencjonowane nie są nijak wydzielane - jest jedna zwarta struktura;

format plikow konfiguracyjnych jest od realizowania logiki???

A jaka to logika? Po prostu wydziela się kawałek drzewa do innego pliku, a w głównym się go dołącza;

a bo niby w yamlu sie nie da?

Przecież napisałem w poprzednim poście, że nie znam wszytkich szczegółów YAML - nie używam go, dawno temu rzuciłem okiem na jego specyfikację; Jeśli coś co podałem istnieje w tamtym formacie - plus dla YAML.

2
furious programming napisał(a):

Naprawdę nie widziałeś nigdy binarnego pliku z przeróżnymi danymi konfiguracyjnymi?

no przeciez chyba nie traktujemy skeszowanej binarki configu jako prawdziwego pliku konfiguracyjnego? na cholere komu takie cos? zeby podczas jakiegos soft faila na produkcji zamiast 5 minut spedzic 2 godziny?

tresc configu sie hashuje i ewentualnie tworzy z tego jakies zserializowane cache - zmiana w tekstowym configu = inwalidacja cache, tylko jak czesto ladujesz config ze robi roznice w ile czasu go zaladujesz?

w aplikacjach enterprise w javie sa gigantyczne configi w xmlu i nikt nie narzeka ze nie ma keszowania ootb bo to nie ma sensu - jezeli cos potrzebuje na startupie ladowac taki dlugi config to i tak bedzie sie baaaardzo dlugo uruchamiac i dodatkowe 0.5 sekundy zyskane na binarce beda niezauwazalne

furious programming napisał(a):

A jaka to logika? Po prostu wydziela się kawałek drzewa do innego pliku, a w głównym się go dołącza;

normalna logika - jak Twoj antyficzer wplywa na security moich uzytkownikow? co, mam sandboksowac biblioteke od configow zeby ktos czegos nie zaincludowal z kosmosu? :D

yaml jest rozszerzalny - jakbym chcial include to moglbym sobie dodac dyrektywe !include wykorzystujac odpowiednie bajery i zdefiniowac dokladnie jak bym chcial zeby ta dyrektywa chodzila - wiekszosc takiego czegos nie potrzebuje, totez yaml nie oferuje tego ootb (security++)

furious programming napisał(a):

Przecież napisałem w poprzednim poście, że nie znam wszytkich szczegółów YAML - nie używam go, dawno temu czytałem jego specyfikację; Jeśli coś co podałem istnieje w tamtym formacie - plus dla YAML.

no to po co porownujesz ten swoj tree struct z yamlem w pierwszym poscie, skoro nie znasz yamla?

o stworzylem sobie taki fajny jezyk programowania podobny do javy, nie znam javy ale CHYBA jest od niej lepszy

3

normalna logika - jak Twoj antyficzer wplywa na security moich uzytkownikow? co, mam sandboksowac biblioteke od configow zeby ktos czegos nie zaincludowal z kosmosu?

Zarówno pojedynczy plik, jak i plik linkowany można załadować osobno, do tego można załadować go w trybie bez linkowania (za pomocą flagi ffNoLinking dodanej do zbioru) i jest to zdefiniowane na poziomie API, nie formatu;

no to po co porownujesz ten swoj tree struct z yamlem w pierwszym poscie, skoro nie znasz yamla?

Niczego nie porównuję - jedyny zapis w pierwszym poście, w którym występuje akronim YAML to ten poniżej:

pierwszy post wątku napisał(a)

Format ten według mnie stanowi ciekawą alternatywę przede wszytkim dla rejestru systemu oraz plików Ini, a także dla takich formatów jak XML, YAML czy TOML [...]

a alternatywa potocznie oznacza inną możliwość, inne rozwiązanie, a nie lepsze rozwiązanie; Więc skoro piszę sobie jakąś desktopową aplikację czy grę, mogę skorzystać z wielu alternatyw - do przechowywania otwartej konfiguracji użyć rejestru, INI, XML, zwykłych plików tekstowych czy dedykowanych plików amorficznych;


Skończmy tę dyskusję, bo atakujesz mnie, tak jakbym kogokolwiek zmuszał do używania mojego formatu, czy jakby weszło ogólnoświatowe zarządzenie, nakazujące pozbycie się wszystkiego co związane z obecnymi formatami; Propozycja nie oznacza konieczności użycia;

Od samego początku prac nad tym formatem zaznaczałem, że tworzę go przede wszystkim dla siebie, bo potrzebuję czegoś ciekawego i wygodnego w obsłudze pod Free Pascalem; Systemu konfiguracyjnego, który pozwoli mi dzielić drzewa na mniejsze części i mniejsze pliki, ale w dalszym ciągu łatwego w obsłudze - głownie za pomocą odwoływania się do wszytkich elementów na podstawie standardowych ścieżek dostępu (jak w Windowsach);

Więc jeśli ktoś nie uważa formatu TreeStructInfo za coś ciekawego czy nie ma nawet najmniejszego zamiaru rzucenia na niego okiem - nie musi odwiedzać tego wątku; Po co się męczyć - ja nikogo nie zmuszam.

2

Właśnie skończyłem pracę nad kolejną wersją biblioteki; Prace końcowe trwały trochę czasu, bo kilka ostatnich tygodni, ale wszystkie założenia zostały zrealizowane;

1. Konwertery wartości

Przede wszystkim przystosowałem konwertery (funkcje) natywnych danych na łańcuchy i wice wersa, aby obsługiwały nowy format zapisu liczb całkowitych w systemach innych niż dziesiętny; Dzięki temu nowym standardem są znaki minusa przed prefiksami, a nie tak jak poprzednio, czyli ~U2;

2. Ładowanie i zapisywanie drzew

Kolejną bardzo ważną rzeczą jest nowy sposób parsowania źródła tekstowego i generowanie wyjścia w tej formie; Nowa wersja biblioteki posiada klasy, które korzystają z dodatkowych list, przechowujących elementy referencjonowane; Dzięki temu wejście można parsować linia po linii, bez konieczności ładowania całego pliku do pomocniczej listy (z czego i tak nie skorzystałem, głównie ze względu na jeden kod ładujący drzewa z różnych źródeł); To samo tyczy się generowania wyjscia tekstowego - wyjście generowane jest linia po linii i od razu sformatowane, a nie tak jak wcześniej, że linie definicji były przesuwane na koniec listy już po wstępnej serializacji;

Wykorzystywanie pomocniczych list dla obiektów elementów referencjonowanych nieco uprościło kod, a także go przyspieszyło, więc uważam to za bardzo ważną zmianę;

3. Drzewa dołączane

Tutaj też jest kilka zmian - na lepsze; Tak jak poprzednio, możliwe jest ładowanie dowolnego pliku bez możliwości obsługi linkowania; Wcześniej była to opcja domyślna, teraz już nie jest; Co więcej, każdy plik może zostać załadowany osobno i bez liknowania zewnętrznych drzew, bez względu na to czy plik faktycznie jest samodzielny, czy jest głównym czy linkowanych plikiem systemu konfiguracji; Dzięki temu API jest bezpieczniejsze dla aplikacji wykorzystującej bibliotekę;

Kolejna i najważniejsza rzecz jeśli chodzi o linkowanie to kompletne zabezpieczenie przed zapętleniem dowiązań; W nowej wersji API nie będzie możliwe dołączenie jednego pliku wielokrotnie (w kilku miejscach drzewa), tworząc wiele identycznych gałęzi (de facto pochodzących z tego samego pliku); Zabezpieczenie to dotyczy także blokady linkowania "samego siebie", co również mogło by rekurencyjnie zapętlić praser i spowodować przepełnienie pamięci; Natomiast sama blokada nie usuwa deklaracji linków z drzew, dzięki temu zawartość pliku i drzewa nie zmieni się po wykryciu kolizji; Element linku w drzewie pozostanie, a jedynie zostanie zignorowany;

Ostatnia rzecz jeśli chodzi o linkowanie kolejnych drzew to użycie dodatkowej listy drzew, zamiast rekurencyjnego ich ładowania; W nowej wersji parser przyjmuje listę drzew i jeśli aktualnie ładowane drzewo zawiera linki - są one dodawane do listy, a sam parser nie ładuje tych drzew od razu; Dzięki temu wszystkie pliki systemu konfiguracji ładowane są liniowo (nie rekurencyjnie) bezpośrednio w metodzie LoadFromFile, co sprawia, że w końcu rzucane przez parsery wyjątki będą wydostawać się poza metodę LoadFromFile; To pozwoli aplikacji używającej biblioteki wyłapywać wyjątki i stosownie na nie reagować;

4. Obsługiwane źródła

Do tej pory biblioteka umożliwiała załadowanie drzewa (lub pełnego systemu konfiguracji) z plików dyskowych, bezpośrednio z list TStrings oraz ze strumieni TStream, a także z kompilowanych zasobów (wkompilowanych plików .res) na podstawie nazwy zasobu lub identyfikatora liczbowego; Nowością jest możliwość załadowania pojedynczego drzewa z zasobów Lazarusa, czyli z wkompilowanych plików .lrs na podstawie nazwy zasobu;

Niestety nie udało mi się ogarnąć metody TLazarusResourceStream.CreateFromID (czyli odpowiednika TResourceStream.CreateFromID), bo nie mam zielonego pojęcia jak to działa; Zasób w pliku .lrs jest tekstowym skryptem, w którym nie można podać liczby jako identyfikatora zasobu; Otrzymywałem wyjątki SIGSEGV przy próbie rozgryzienia tej metody, niestety na próżno; Próżno też szukać instrukcji w dokumentacji, bo opis tej metody jest obskórny... Dlatego też póki co nie będzie takiej możliwości, ale w przyszłości może się to zmienić;

Pozostałe zmiany

Zmian i ulepszeń jest więcej, ale są to małe pierdółki jak formatowanie kodu, nazewnictwo, reorganizacja kolejności deklaracji i definicji klas itd.; Wszystkich zmian nie ma sensu wypisywać, bo te pozostałe mają zasięg lokalny;

Nowe API nie będzie kompatybilne z poprzednim, tak samo jak nowy format nie będzie kompatybilny z poprzednim; W API zmieniły się nieco instrukcje ładowania drzew (zostały wydzielone z konstruktorów do metod LoadFrom*), a także lekko zmieniło się nazewnictwo klas i niektórych metod; Co do samego formatu - nieco zmieniła się składnia tekstowych plików (rozwinięte frazy kluczowe, nowy zapis deklaracji linków do plików dołączanych itd.), a także budowa plików binarnych (nagłówek pliku oraz zapis głównego węzła drzewa);

Funkcjonalność samego formatu praktycznie nie zmieniła się - inny jest tylko zapis pewnych elementów; Pozostało tylko wszystko porządnie przetestować, aby mieć 100% pewności co do niezawodności i słabych punktów biblioteki; Przede mną jeszcze dużo pracy, bo co prawda biblioteka już prawie gotowa, ale trzeba jeszcze przygotować specyfikację dla nowej wersji formatu, a także dokumentację i tutorial dla nowego API;

Jeszcze miesiąc-dwa i będzie gotowe.

1
furious programming napisał(a):

Niestety nie udało mi się ogarnąć metody TLazarusResourceStream.CreateFromID (czyli odpowiednika TResourceStream.CreateFromID), bo nie mam zielonego pojęcia jak to działa; Zasób w pliku .lrs jest tekstowym skryptem, w którym nie można podać liczby jako identyfikatora zasobu; Otrzymywałem wyjątki SIGSEGV przy próbie rozgryzienia tej metody, niestety na próżno; Próżno też szukać instrukcji w dokumentacji, bo opis tej metody jest obskórny... Dlatego też póki co nie będzie takiej możliwości, ale w przyszłości może się to zmienić;

Aż ciężko się to czyta... Może spróbuj jakiejś dojrzałej technologii? Praca z czymś takim to strata życia na rozwiązywanie dziwnych problemów.

0

Aż ciężko się to czyta...

Żeby wiedzieć co napisałem, trzeba znać to, o czym napisałem;

Praca z czymś takim to strata życia na rozwiązywanie dziwnych problemów.

Strata życia to przepisywanie całej biblioteki tylko dlatego, że jedna rzadko używana metoda sprawia kłopot;

Hmm... już wiem jak działa ta metoda.

0

Piszesz ze praktycznie brak zmian a pojawia sie brak kompatybilnosci z poprzednia wersja. Cos jest tu nie tak.

0

Nie nie nie - w poprzednim długim poście przecież opisałem same zmiany, więc jak nie ma zmian? To co się faktycznie "praktycznie nie zmieniło" to funkcjonalność formatu - o tym napisałem pod koniec posta spod linku:

furious programming napisał(a)

Funkcjonalność samego formatu praktycznie nie zmieniła się - inny jest tylko zapis pewnych elementów;

I to prawda - funkcjonalność pozostała bez zmian, nadal obsługiwane są dwie formy zapisu (tekstowa i binarna), nadal używane są wcześniej obsługiwane elementy i typy danych dla wartości atrybutów, a także nadal możliwe jest wielopoziomowe referencjonowanie elementów i drzew z plików dołączanych, mieszając dowolnie dwie formy; Natomiast to co zmianie uległo to w nieznacznym stopniu składnia tekstowych plików oraz także w nieznacznym stopniu budowa początkowego fragmentu plików binarnych (sygnatura oraz zapis głównego węzła drzewa);

A że nieco zmieniła się składnia oraz nagłówek binarnych plików to automatycznie kompatybilność wsteczna została zerwana - stąd nowa wersja ma oznaczenie 2.0, a nie np. 1.1; W razie czego pytaj - postaram się odpowiedzieć.

2

Format jest na tyle ciekawy że zainspirowało mnie to do pójścia w trochę inny obszar niż aplikacje desktopowe w Lazarusie, więc na początek postanowiłem że napiszę to w PHP. I mam w głębokim poważaniu prześmiewcze komentarze fanboyów pythona, javy, C#, później zamierzam również pójść i w tym kierunku :-)

Zamierzam pójść w trochę innym kierunku niż to co jest w obecnym API pod FPC, ponieważ spróbuję poeksperymentować coś nie tylko z zapisywaniem i odczytywaniem konfiguracji i to nie tylko standardowe stringi czy liczby całkowite albo rzeczywiste ale również dane typu JSON, zapamiętywanie tablic a jeszcze bardziej interesuje mnie zagadnienie serializacji i deserializacji klas. Nie wiem jak to wyjdzie z tym formatem i czy to będzie akurat dobre podejście więc prosiłbym o jakieś wskazówki.

Kod mam na githubie i pierwsza wersja jest tu:
https://github.com/dariuszrorat/phpTreeStructInfo

Jest tu na bank znacznie prościej niż w przypadku Free Pascala. Jeśli chodzi o mój wkład, to chciałbym zainspirować @furious programming i innych którzy już w tym uczestniczą do pójścia nieco dalej a moim zdaniem może być tu wiele korzyści :-)

1
drorat1 napisał(a)

Format jest na tyle ciekawy że zainspirowało mnie to do pójścia w trochę inny obszar niż aplikacje desktopowe w Lazarusie [...]

Momencik, bo chyba coś jeszcze nie jest jasne i muszę doprecyzować;

Format TreeStructInfo nie jest przeznaczony tylko dla Lazarusa i desktopów; Tak jak każdy inny format plików, tak i ten przeznaczony jest do dowolnych konfiguracji, bez względu na to czy będą z nich korzystać aplikacje desktopowe (np. programy narzędziowe, użytkowe czy gry), czy mobilne, czy serwerowe; Sam format określa jedynie sposób zapisu danych w takich plikach, czyli funkcjonalność; Określa to, co musi wiedzieć każdy chcący używać takich plików czy systemów konfiguracyjnych, aby poprawnie przygotowywać pliki;

Natomiast przygotowane przeze mnie API dla FPC można wykorzystać na każdej platformie, a każdym systemie i w każdej aplikacji, którą potrafi skompilować/zbudować kompilator FPC; Czyli API może być użyte w dowolnym programie, pod warunkiem że skompilowanym za pomocą FPC;

Podsumowując - format może być używany wszędzie tam, gdzie można w plikach umieszczać konfiguracje; Pełna funkcjonalność formatu (samego formatu, nie biblioteki dla FPC) opisana jest w specyfikacji na stronie projektu; Natomiast to z czego zbudowana jest biblioteka do obsługi takich plików opisane jest w dokumentacji API, a to jak używać API opisane jest w specjalnie do tego celu przygotowanym tutorialu (wszystko na stronie projektu w odpowiedzich działach);

To chyba tyle - teraz wszystko powinno być klarowne :]


Prośba o jedną rzecz @drorat1 - wstrzymaj się na kilka dni z produkcją kodu, dlatego że w tej chwili pracuję nad specyfikacją do drugiej wersji formatu; Dokument zostanie wrzucony na stronę projektu za kilka dni - dzięki temu swoją bibliotekę będziesz mógł stworzyć od razu pod nową wersję formatu;

Zamierzam pójść w trochę innym kierunku niż to co jest w obecnym API pod FPC, ponieważ spróbuję poeksperymentować coś nie tylko z zapisywaniem i odczytywaniem konfiguracji i to nie tylko standardowe stringi czy liczby całkowite albo rzeczywiste ale również dane typu JSON, zapamiętywanie tablic a jeszcze bardziej interesuje mnie zagadnienie serializacji i deserializacji klas.

To w jaki sposób przechowuje się dane w atrybutach jest opisane w specyfikacji; Wymienione w specyfikacji typy danych to te najpopularniejsze, których obsługa to mus; Natomiast w atrybutach można zapisywać dane dowolnego typu, o ile da się sensownie zaimplementować metody serializacji i deserializacji takich danych;

Nie wiem jak to wyjdzie z tym formatem i czy to będzie akurat dobre podejście więc prosiłbym o jakieś wskazówki.

Przede wszystkim aby napisać jakiekolwiek API, najpierw trzeba poznać każdy aspekt samego formatu; Do tego potrzebna jest specyfikacja (i nad nią obecnie pracuję), dlatego też musisz się wstrzymać z kodowaniem na kilka dni; Dokument opisujący wszystkie zagadnienia formatu (czyli specyfikację) wrzucę na stronę projektu za kilka dni, jak tylko opiszę wszystko co konieczne; Następnie zabiorę się za dokumentację dla mojego nowego API i za tutorial - będzie komplet pomocy;

W razie czego pytaj @drorat1 w tym wątku czy przez PM - postaram się wszystko jak najdokładniej opisać.

1

No, nowa wersja formatu została kilka dni temu zdefiniowana i specyfikacja nowej wersji dostępna jest tutaj:

https://tsinfo.4programmers.net/pl/format/2.0.htm

Jest to dopiero wstępna wersja dokumentu, w którym to mogą pojawić się jeszcze małe poprawki (jakby się okazało, że coś nie jest doprecyzowane lub po prostu bez sensu); W każdym razie (ucząc się na błędach) nowy dokument powinien być sensowniejszy, dokładniej wyjaśniać wszelkie aspekty związane z formatem i zawierać o wiele mniej dwuznacznych sformułowań, w przeciwieństwie do specyfikacji dla pierwszej wersji;

Tę informację kieruję w szczególności do dotychczasowych zainteresowanych, czyli @spartanPAGE, @Wizzie i @drorat1;

Natomiast teraz czas na zaktualizowanie źródeł i przygotowanie do nich dokumentacji oraz tak jak w przypadku API dla pierwszej wersji formatu - także tutorialu; Nie wiem ile to potrwa, ale postaram się jak najszybciej wszystko napisać; W razie czego dam znać tutaj.

1

Widzę, że wątek jest dość chętnie odwiedzany, choć powyższy post pojawił się ponad miesiąc temu - cieszę się;

Co by nieco zaspokoić apetyt na nowinki związane z formatem i API dla Lazarusa - prace idą pełną parą; Kończę uzupełniać dokumentację - zostało opisać ostatnie dwie z siedemnastu klas, pozostałe moduły są już opisane; Następnie pozostanie przygotować dwa dokumenty tutorialu oraz wrzucić kod z załącznikami i zaktualizować kontent na serwerze; Specyfikacja jest gotowa i póki co nie wprowadzałem do niej poprawek;

Jeszcze tydzień-dwa i premiera API, kandydującego do wersji stabilnej.

1

Znalazłem potwornego buga w funkcji ValueToDateTime z modułu TSInfoUtils.pp - uniemożliwiał on dekonwersję składowych daty, jeśli w wejściowym łańcuchu (czyli surowej wartości atrybutu) składowe te oddzielone są separatorem FormatSettings.DateSeparator; Pomimo setek testów funkcji konwertujących, jakimś cudem umknęło to mojej uwadze...

Usunięcie tego buga było bardzo proste, choć funkcje konwersji daty i czasu są dość długie i skomplikowane; W każdym razie teraz już wszystko jest w porządku, przetestowałem poprawiony kod i już nie sprawia żadnych problemów;

Przykład dość swobodnego zapisu daty i czasu poniżej; To tylko test, stąd taka dziwna maska:

uses
  TSInfoFiles, TSInfoTypes, SysUtils, DateUtils;

const
  DATETIME_MASK = UTF8String('"Dziś jest" DDDD, D/MM/YYYY, "godzina" H:NN AM/PM "(w tym sekund" SS")"');
var
  tsiConfig: TSimpleTSInfoTree;
  dtValue: TDateTime;
begin
  FormatSettings.TimeAMString := 'am';
  FormatSettings.TimePMString := 'pm';

  tsiConfig := TSimpleTSInfoTree.Create('C:\Config.tsinfo', [tmTextTree, tmAccessWrite]);
  try
    dtValue := EncodeDateTime(2015, 11, 22, 20, 20, 30, 0);
    tsiConfig.WriteDateTime('DateTime 1st', DATETIME_MASK, dtValue);

    dtValue := 0; // to akurat nie jest potrzebne - w razie niepowodzenia dekonwersji, metoda zwróci 0

    dtValue := tsiConfig.ReadDateTime('DateTime 1st', DATETIME_MASK, 0);
    tsiConfig.WriteDateTime('DateTime 2nd', DATETIME_MASK, dtValue);
  finally
    tsiConfig.Free();
  end;

  Write('done...');
  ReadLn();
end.

Powyższy testowy program jest dość prosty w działaniu; Uzupełniamy zmienną dtValue w jakąś wartość daty i czasu - tutaj akurat skorzystałem z dnia dzisiejszego; Następnie zapisujemy tę wartość do atrybutu, gdzie wartości składowych oraz ich umiejscowienie w ciągu znaków wartości definiuje maska ze stałej DATETIME_MASK; Następnie zmienną zerujemy, do niej z powrotem wczytujemy wartość daty i czasu z atrybutu DateTime 1st oraz tę wartość wpisujemy do drugiego atrybutu - DateTime 2nd; Na koniec drzewo zapisywane jest do pliku w destruktorze (to określa tryb tmAccessWrite z konstruktora) i tyle; jeśli zapis i odczyt daty i czasu przebiegną pomyślnie - wartości abu atrybutów będą takie same;

Zawartość pliku C:\Config.tsinfo po odpaleniu programu przedstawiać się będzie następująco:

treestructinfo "2.0"
  attr DateTime 1st "Dziś jest niedziela, 22-11-2015, godzina 8:20 pm (w tym sekund 30)"
  attr DateTime 2nd "Dziś jest niedziela, 22-11-2015, godzina 8:20 pm (w tym sekund 30)"
end tree

Czyli wszystko gra, konwersja poprawna, dekonwersja także;


Tak swobodny sposób zapisu daty i czasu jest dla mnie bardzo ważny - założeniem formatu jest duża swoboda formy zapisu datych w atrybutach; Dziwić trochę może taka możliwość (choć przecież nie trzeba z niej korzystać, prawda?), jednak ma to swoje duże plusy - wartość daty, czasu lub daty i czasu zapisana razem z dodatkowymi podciągami (np. Dziś jest czy godzina), pozwala na łatwą dekonwersję do typu TDateTime, za pomocą tego samego łańcucha maski, a dodatkowo pozwala na odczyt jako łańcucha znaków i jego bezpośrednie wyświetlenie np. w etykiecie, bez dodatkowej konwersji; Całość wspiera UTF-8, więc współgra z natywnym dla LCL kodowaniem;


Jeśli o ogólne informacje na temat nowej wersji formatu chodzi, to jestem w połowie pisania tutoriala dla klasy TSimpleTSInfoTree; Następnie pozostanie napisanie kursu obsługi klasy TTSInfoTree (większość mogę przekopiować z kursu dla API w wersji 1.0, bo ta klasa praktycznie nie zmieniła się) i to będzie wszystko;

Mam nadzieję, że na koniec listopada wszystko będzie gotowe - prawie będę miał prezent pod choinkę.

2

Po kilku ładnych miesiącach żmudnych prac nad rozwojem projektu, kolejna wersja biblioteki do obsługi plików i systemów konfiguracyjnych TreeStructInfo została wydana; Od wczoraj w sieci dostępne są źródła biblioteki w postaci gołych modułów dla kompilatora FPC oraz paczka dla Lazarusa, możliwa do dołączenia do dowolnego projektu; Biblioteka obecnie znajduje się w wersji beta i możliwa jest do pobrania zarówno ze strony projektu, jak i z repozytorium w serwisie GitHub;

Na stronie projektu są także dostępne materiały edukacyjne, czyli przede wszystkim kompletna i szczegółowa dokumentacja API, opisująca każdy elemenet wchodzący w skład oficjalnej biblioteki, a także tutorial, w którym pokazane są sposoby wykorzystania wszystkich publicznych metod z dwóch głównych klas do obsługi plików konfiguracyjnych;

Poniżej podaję linki do odpowiednich stron:

4

Kilka miesięcy minęło i nadszedł czas na kolejną aktualizację;

Tym razem jest to spory krok do zwiększenia bezpieczeństwa obsługi plików konfiguracyjnych, a tym samym krok w tył, jeśli chodzi o funkcjonalność formatu TreeStructInfo; Z racji tej, że linkowanie plików jest mocno kłopotliwe, ciężko jest wypracować rozwiązanie multiplatformowe, a także zabezpieczenie procesu linkowania przed błędami jest niemalże awykonalne - możliwość tworzenia wieloplikowych systemów konfiguracyjnych, a tym samym samo ich dołączanie za pomocą linków, zostaje całkowicie usunięte;

Jednak nie zmienia to faktu, iż wszytkie pozostałe elementy formatu są i będą nadal wspierane; Pozostaje składnia (oprócz słów i fraz kluczowych dotyczących linków), liniowa budowa plików, typy danych chowane w atrybutach, komentarze, referencjonowanie elementów oraz forma tekstowa i binarna;

Tak więc od dziś linki i linkowanie oficjalnie nie istnieją; Decyzję podjąłem po dłuższym namyśle i raczej nie zamierzam jej cofnąć; Oprócz mojego API, nie pojawiło się jeszcze żadne inne, więc nikt na tym nie ucierpi; Specyfikację formatu w wersji 2.0 dziś poprawiłem, API poprawiłem w poprzednich dniach i skończyłem wczoraj - teraz jest lżejsze i nieco szybsze, z racji braku obsługi linkowania; Póki co do pobrania z repo, a w najbliższych dniach poprawię jego dokumentację oraz tutorial;

Linki:

Edit: Wszystkie dokumenty (specyfikacja, dokumentacja i tutorial) zostały poprawione.

0

Tak z ciekawości: czy masz jakieś źródła w ogóle, albo jesteś w stanie powiedzieć czy ktoś z tego korzysta?

0

Ja z tej biblioteki korzystam i jestem bardzo zadowolony; Swój zamknięty projekt wykorzystuje moją libkę do trzymania konfiguracji interfejsu, do przechowywania statystyk, a także do trzymania ustawień niektórych komponentów, w postaci list typu TStringList; Biblioteka pozwala ładować drzewka z różnych źródeł, więc komponenty w sobie mogą je przechowywać :]

Nie wiem czy ktoś oprócz mnie z niej korzysta, dlatego że na tym forum mało jest użytkowników piszących w Lazarusie; Wersji dla Delphi nie ma, bibliotek w innych językach póki co także nie; Jedyne czym dysponuję to tabelkami aktywności na stronie projektu, np. tą:

summary.png

W kwietniu tego roku była odnotowano najwyższą liczbę unikalnych wejść równą 1939;


Głównym powodem tego jest fakt, iż poza 4programmers nie opisywałem tego formatu ani API, więc trudno, żeby ktokolwiek spoza tego serwisu wiedział; Jednak nie ogłaszałem się celowo, dlatego że nie byłem pewien co do ostatecznej formy formatu i jego funkcjonalności; Do tego miałem kilka problemów z API - szybko wychodzące nowe wersje FPC, a do tego teraz kolejna, z nowym silnikiem unikodowym;

Jednak format dopracowałem, usunąłem (już dawno temu, bo to był poważny fail, wynikający z mojej niewiedzy) jedną rzecz nieprzenośną pomiędzy językami programowania, do tego pozbyłem się linkowania, dzięki czemu cała biblioteka nie operuje na ścieżkach do plików, co czyni ją przenośną również pomiędzy platformami programowymi;

Zrobiłem to co chciałem zrobić i teraz mogę jechać dalej, czyli rozreklamować format (rozpocznę od oficjalnego forum Free Pascala) i pozyskać większą liczbę beta testerów, aby w niedługim czasie móc opublikować stabilną wersję API;


Nie ukrywam, że przydałaby mi się pomoc z przygotowaniem highlighterów dla edytorów tekstowych, z których programiści korzystają; Ja skromnie korzystam jedynie z systemowego Notatnika oraz z programu Notepad++ - więcej nie potrzebuję; Do tego drugiego dorobiłem sobie kolorowanie, jednak nie ma możliwości zrobić tego bezbłędnie - z tego co się dowiedziałem, nie ma obsługi wyrażeń regularnych, więc kolorowanie rozwala użycie znaku cudzysłowu wewnątrz wartości atrybutu (co jest zgodne ze specyfikacją i obsługiwane przez API); Innych edytorów nie znam (np. VIM) i nie potrafię dorobić kolorowania, choć czytałem dokumentacje na ten temat; Dla mnie to czarna magia...

Poza tym pozostaje problem z plikami binarnymi; Dlatego też wciąż zastanawiam się, czy na siłę próbować coś dorobić do edytorów, aby konwertowały zawartość binarną na tekstową (przy odczycie) i odwrotnie (przy zapisie), czy stworzyć własny edytor (to akurat nie problem).

0

Gdybyś udostępnił dll eksportujący standardowe funkcje w stylu C (w C++ kiedyś pisało się po prostu extern "C"), to każdy by mógł z niej korzystać w każdym kompilatorze i w każdym języku i nie wiedzieć nawet co to Pascal ani co to Lazarus.

Jak rozumiem, tego nie ma i nie ma nawet w planach, trzeba mieć Lazarusa i basta. W takim razie nie wróżę popularności bo i sam Lazarus jak wiesz zapewne nie jest póki co zbyt szeroko wykorzystywany

1

Jak rozumiem, tego nie ma i nie ma nawet w planach, trzeba mieć Lazarusa i basta.

Powstanie biblioteki dll jest w planach i dyskutowałem na ten temat ze @spartanPAGE miesiąc temu, może dwa; Jednak czasu nie mam zbyt dużo, więc prace nad projektem idą powoli - zresztą nigdzie się nie spieszy; Projekt uruchomiłem dokładnie 22 kwietnia 2013, więc minęło już ponad 3 lata; Jest on ciągle rozwijany, więc nie ma co się martwić - nowości będą się pojawiać;

W takim razie nie wróżę popularności bo i sam Lazarus jak wiesz zapewne nie jest póki co zbyt szeroko wykorzystywany

Projekt ten trzy lata temu rozpocząłem z myślą jedynie o sobie - miał mi on zastąpić pliki INI, bo format ten jest ubogi, a także XML, z racji topornego i ciężkiego API; Dopiero po jakimś czasie wpadłem na pomysł, aby całość opublikować, dlatego powstała strona projektu; Specyfikacja formatu oraz dokumentacja i tutorial API przydają się również mnie i to fakt - czasem sam z nich korzystam; Tak więc na popularności jakoś szczególnie mi nie zależy.

0

Trochę nie ogarniam. Zamiast mieć dll i pisać tylko wrappery (np do .net czy c++), a core by był wspólny, pisany i utrzymywany przez ciebie, ktoś inny czyta twoje dokumentacje api i pisze dam znów to samo od zera tyle że w C++ ?

WTF?

1

Problem w tym, że domyślnie nie miał to być projekt publikowany, a tylko dla mnie, ze zwykłym API; Dopiero rok później otworzyłem stronkę i udostępniłem kod gotowej paczki; A że nie było czasu na przepisywanie wszystkiego od nowa to tak zostało;

Edit: Zapomniałem jeszcze o jednym - nie każda aplikacja jest instalowana; W chwili obecnej, moje API mogę wykorzystać do stworzenia dowolnej aplikacji konsolowej czy okienkowej (przenośnej, jako samotny plik wykonywalny), a także do stworzenia dowolnego własnego komponentu; Jeśli cały silnik przetwarzający pliki siedziałby w bibliotece dll to było by to dużym utrudnieniem; Każdy program musiałby albo ciągnąć za sobą to dll, albo mieć tę bibliotekę w zasobach i cudować z eksportami;

Tak więc kompletne API w postaci zwykłych plików źródłowych jest potrzebne i konieczne, a bibliotekę dll należy traktować jako dodatek, przydatny dla tych, którzy nie mają czasu lub nie wiedzą jak przetwarzać pliki konfiguracyjne.

2

Mała wzmianka o nowych elementach w oficjalnym API;

Otrzymałem w ostatnim czasie na adres e-mail wiadomość z pytaniem o zapis danych innego typu niż obecnie obsługiwane przez bibliotekę; Konkretnie było to pytanie o zapis współrzędnych punktów w postaci liczb zmiennoprzecinkowych; W chwili obecnej, klasa TSimpleTSInfoTree nie umożliwia zapisu lub odczytu takich współrzędnych za pomocą jednej metody, tak jak ma to miejsce np. w przypadku zapisu/odczytu współrzędnych punktu jako liczb całkowitych (metody WritePoint i ReadPoint); Głównie dlatego, że Free Pascal nie posiada takiego typu danych w RTL; Co nie zmienia faktu, iż takie współrzędne można zapisać do dwóch atrybutów, wykorzystując standardowe metody WriteFloat oraz ReadFloat;

Dotychczas, aby zapisać dane innego typu niż obsługiwane, należało we własnym zakresie konwertować dane na ciąg znaków i odwrotnie i skorzystać z metod WriteString oraz ReadString; Oczywiście jeśli chodzi o zapis danych do jednego atrybutu, w postaci pojedynczej wartości (lub jak kto woli - wartości jednoliniowej);

Jednak takie sposoby zapisu standardowo nieobsługiwanych typów danych są brzydkie i mogą być nieczytelne; Dlatego też wprowadziłem lekką modyfikację - przeniosłem pola FReadOnly i FModified z sekcji private do protected, aby były widoczne w klasach dziedziczących z klasy TSimpleTSInfoTree, które są zaimplementowane w innym module; To samo uczyniłem z metodami FindElement, FindAttribute oraz FindNode - także od teraz są w sekcji protected;

Po co taka zmiana?

Dzięki tej modyfikacji, aby dodać obsługę innego typu danych, nie musimy modyfikować kodu biblioteki; Wystarczy, że w którymś ze swoich modułów (modułów projektu używającego paczki TreeStructInfo) stworzymy sobie klasę helpera, rozszerzającą bazową klasę drzewa, która to zawierać będzie własnoręcznie zdefiniowane metody; Sprawi to, że do klasy TSimpleTSInfoTree wstrzyknięte zostaną nowe metody, które także dostępne będą w klasie TTSInfoTree, będąca rozszerzoną wersją klasy bazowej; Uwidocznienie wspomnianych wyżej pól i metod klasy pozwoli zachować identyczną budowę metod zapisujących i odczytujących (wyjątki związane z trybem tylko do odczytu, zmiana stanu zmodyfikowania drzewa czy wyszukiwanie atrybutu na podstawie ścieżki dostępu);

Przykład

Dla przykładu podam sposób (tylko ramkę) na rozszerzenie funkcjonalności bazowej klasy TSimpleTSInfoTree za pomocą klasy helpera, o zapis i odczyt danych jakiegoś własnego typu:

type
  TFloatPoint2D = record
    X, Y: Double;
  end;
 
type
  TSimpleTSInfoTreeHelper = class helper for TSimpleTSInfoTree
  public
    procedure WriteFloatPoint(const AAttrPath: String; AFloatPoint2D: TFloatPoint2D);
    function ReadFloatPoint(const AAttrPath: String; ADefault: TFloatPoint2D): TFloatPoint2D;
  end;
 
{...}
 
procedure TSimpleTSInfoTreeHelper.WriteFloatPoint(const AAttrPath: String; AFloatPoint2D: TFloatPoint2D);
var
  attrWrite: TTSInfoAttribute;
begin
  if FReadOnly then
    ThrowException(EM_READ_ONLY_MODE_VIOLATION)
  else
  begin
    attrWrite := FindAttribute(ExcludeTrailingIdentsDelimiter(AAttrPath), True);
 
    if attrWrite <> nil then
    begin
      attrWrite.Value := { tutaj konwersja parametru AFloatPoint2D } ;
      FModified := True;
    end;
  end;
end;
 
function TSimpleTSInfoTreeHelper.ReadFloatPoint(const AAttrPath: String; ADefault: TFloatPoint2D): TFloatPoint2D;
var
  attrRead: TTSInfoAttribute;
begin
  attrRead := FindAttribute(ExcludeTrailingIdentsDelimiter(AAttrPath), False);
 
  if attrRead = nil then
    Result := ADefault
  else
    Result := { tutaj konwersja wartości attrRead.Value } ;
end;

W miejsce komentarzy należy wstawić kod, który będzie służył do konwersji danych natywnych na ciąg znaków i odwrotnie (jaki chcemy); Nie musimy tego robić ręcznie - w module TSInfoUtils.pp istnieje kupa metod służących do konwersji danych, ale i nie tylko; Można korzystać także ze stałych oraz typów danych, zawartych w pozostałych modułach biblioteki (np. ze stałej COORDS_DELIMITER);

Druga nowość

Drugą i póki co ostatnią nowością są bezparametrowe metody SwitchTreeForm oraz SwitchTreeAccess; Pierwsza służy do zmiany formy drzewa (z tekstowej na binarną i odwrotnie), a druga do zmiany trybu dostępu (tryb tylko do odczytu na tryb do odczytu i zapisu i odwrotnie);

Drzewo załadowane w trybie tylko do odczytu charakteryzuje się tym, że w destruktorze klasy nie zostaje automatycznie zapisane do pliku; Nie zmienia to jednak faktu, iż zawartość drzewa w pamięci można modyfikować - dzięki temu zapis drzewa możemy przeprowadzić tylko i wyłącznie w specyficznej sytuacji, używając metody UpdateFile;

Podsumowanie

Póki co zmiany istnieją jedynie w repozytorium, ale niebawem zostanie wydana już czwarta wersja beta biblioteki, do której nowe elementy zostaną dodane na stałe; W tym samym czasie powinna już być poprawiona dokumentacja API, ale w chwili obecnej, póki aktualna jest wersja 2.0 beta 3, dokumentacja jej dotyczy i ją opisuje;

PS: Ten wątek traktuję raczej jako bloga, przez dłuższy czas głównie podając nowe informacje związane z tym projektem, więc nie oczekuję rozwinięcia dyskusji; W razie czego oczywiście można komentować :]

0

Nowa wersja biblioteki wydana - TreeStructInfo 2.0 beta 4; Linki do pobrania paczki lub gołych modułów tutaj:

W niedługim czasie dodam także nowy artykuł na stronie projektu (w kategorii tutorial API), opisujący sposób na rozszerzenie funkcjonalności bazowej klasy, w celu zapisu i odczytu danych nieobsługiwanych typów; Wykorzystam do tego jakiś często używany typ danych, np. macierz liczb (może nawet skuszę się na macierz dwuwymiarową), ale to się jeszcze zobaczy.

0
AreQrm napisał(a):

Tak z ciekawości: czy masz jakieś źródła w ogóle, albo jesteś w stanie powiedzieć czy ktoś z tego korzysta?

Ostatnio ktoś spytał we wrześniu zeszłego roku. Potem już tylko posty autora o coraz to nowych wydaniach, lecz nikt się nie zainteresował

4

@Hau Hau - na zapytanie @AreQrm odpowiedziałem półtora miesiąca temu, jakbyś nie zauważył; Po drugie, ten wątek nie służy do jakichś zapisów, a właśnie do prezentowania nowości związanych z tym projektem;

Więc po co ten post?

Jak ukończę pracę nad ostateczną wersją beta biblioteki 2.0 to dam znać nie tylko tutaj, ale i na forum Lazarusa, gdzie chętnych do testowania i używania na pewno znajdę; Popularność Free Pascala w Polsce jest znikoma, dlatego też nie oczekuję fali zainteresowanych z tego serwisu; Natomiast w innych krajach sytuacja jest zupełnie inna - największym zainteresowaniem Lazarus cieszy się wśród Rosjan i Niemców, więc wiem gdzie szukać chętnych; Ale najpierw dokończę co mam zaczęte, żeby nie prezentować projektu rozgrzebanego do połowy;


Co nowego - wprowadzam kojeną modyfikację w bibliotece, dzięki której rozszerzanie bazowej klasy o obsługę dodatkowych typów danych będzie łatwiejsze i czytelniejsze; Samą bazową klasę można już rozszerzać helperem, ale dodatkowo postanowiłem zrobić coś, aby funkcje konwersji nie pelentały się gdziekolwiek;

Aby móc ujednolicić rozszerzanie bazowej klasy, wszystkie procedury i funkcje z modułu TSInfoUtils.pp, które umożliwiały dwustronną konwersję danych, przeniosłem do nowej klasy TTSInfoDataConverter (od teraz są to metody statyczne); Podczas rozszerzania bazowej klasy, najpierw tworzy się helper właśnie dla klasy TTSInfoDataConverter, dodając metody konwersji (w stylu IntegerToValue i ValueToInteger); Następnie tworzy się drugi helper dla klasy TSimpleTSInfoTree, dodając właściwe metody zapisu i odczytu danych (w stylu WriteInteger i ReadInteger); Dobrym pomysłem jest stworzenie sobie dodatkowego modułu, np. TSInfoHelpers.pp i wrzucenie tych dwóch helperów do tego modułu;

Dzięki temu rozszerzenie bazowej klasy to utworzenie dwóch klas helperów, dodając do nich po dwie metody (dwie do konwersji oraz dwie do zapisu/odczytu do/z atrybutu); Jest to najczytelniejsze i najprostsze rozwiązanie;


Zmiany wprowadzone w kodzie biblioteki są już w repozytorium; Kolejnym krokiem jest uzupełnienie dokumentacji; Na koniec dorzucę jeszcze nowy artykuł na stronie tutoriali, w którym dokładnie opiszę sposób na rozszerzenie klasy o obsługę własnego typu danych;

Mam już zaklepany testowy projekt, w którym dodana została obsługa zbioru własnych enumów i ich zapis do atrybutu jako wartości jednoliniowej; Kod miodzio - krótki, czytelny, z obsługą błędów konwersji łańcuchów na enumy (korzystający z RTTI) oraz możliwości zwrócenia domyślnego zbioru, podczas niepowodzenia konwersji.

1

Finalna beta-wersja biblioteki wydana - nosi numer 2.0 beta 5 (to już ostatnia wersja testowa);

Tak jak napisałem w poprzednim poście, wszystkie funkcje i procedury służące do konwersji danych opakowałem w klasę - klasa ta nosi nazwę TTSInfoDataConverter i znajduje się w module TSInfoUtils, czyli tam gdzie gołe funkcje/procedury istniały wcześniej; Wszystkie metody tej klasy są statyczne, więc można z nich korzystać bez konieczności tworzenia obiektu tej klasy; Zauktualizowałem także repozytorium, różne dokumenty na stronie projektu, w tym przede wszystkim dokumentację API, a także mapę strony (doszedł nowy artykuł);

Linki do pobrania źródeł:

Linki do materiałów:

W artykule na temat obsługi własnego typu danych, podałem przykład rozszerzenia bazowych klas o możliwość zapisu i odczytu zbioru enumów z wykorzystaniem RTTI, zawierającego rodzaje potworków w grze typu Bomberman (@babubabu powinno się spodobać :]); Artykuł ten jest dość długi - być może nieco przesadziłem; W każdym razie nie można narzekać, że o czymś nie napisałem - zadbałem o wszystkie szczegóły.

2

Kilka godzin temu udostępniłem w dziale pobierania plik XML umożliwiający kolorowanie składni tekstowych plików TreeStructInfo dla edytora Notepad++ (teoretycznie dla wersji 6.9.2, ale na starszych wersjach też działa);

Niestety nie jest on idealny, ale to co jest spokojnie wystarczy :]

0

Przed chwilą udostępniłem w dziale pobierania na stronie projektu oraz w repozytorium bibliotekę w wersji 2.0 RC1, która jak z tagu wynika, jest pierwszym kandydatem do wersji stabilnej; Wszystkie materiały edukacyjne (dokumentacja oraz trzy tutoriale) dokładnie opisują jej wnętrzności, więc śmiało można z nich korzystać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1