StructReader
Wpadłem na pomysł prostego serializer’a, który by potrafił czytać dane z pliku podzielonego na sekcje i zapisywać je do prostej struktury – agregata. Miał być to szablon funkcji, który pobierałby jako jeden z argumentów wskaźnik do tej struktury, następnie wyliczał miejsce zmiennej w strukturze, na podstawie tablicy z typami (enum) i w końcu zapisywał przeczytane dane odpowiednio, sformatowane przez bibliotekę standardową. Niestety jak się okazało (czego do tej pory nie wiedziałem) miedzy składnikami klasy, struktury są przerwy, więc nie można skorzystać z wskaźnika, którego chciałem przesuwać o rozmiar przeczytanego typu, gdyż spowoduje to błędy zapisu.
Na szczęście rozwiązanie tego problemu okazało się bardzo proste i jest o wiele bardziej uniwersalne, otóż zamiast wskaźnika na obiekt struktury, przekazuję funkcji (ponieważ szablon jest już niepotrzebny) tablicę wskaźników do zmiennych i jej rozmiar. Dzięki niej wiem gdzie w pamięci znajduje się dana zmienna. Rozwiązanie to ma też inna zaletę, ponieważ do funkcji mogę przekazać nie tylko obiekty struktury, ale również dowolne obiekty nienależące do struktury.
Oto przykładowy plik cfg:
1 2 3 4 5 6 7 8 | Sekcja1{ // Komentarz } // Komentarz 2 Sekcja2 { zmienna1 = 3.14; // Komentarz np. opisuje jaki to typ, tu float } |
Jak widać schemat jest prosty:
- Sekcje oznaczamy nazwą i klamerkami
- Komentarze tylko po //, są ważne do końca linii
- Nazwy zmiennych nie są brane pod uwagę, liczy się znak ‘=’ i ‘;’, pierwszy rozpoczyna czytanie wartości, drugi kończy.
PS. Schemat pliku zmyślony z Regedit’a :).
W kodzie wygląda to tak:
1 2 3 4 5 6 7 8 9 10 11 | // Tworzymy tablicę z typami int types[] = { TYPE_FLOAT }; // Przykładowo float // Zmienna float temp; // Tablica ze wskaźnikami void* pointers = { &temp }; // Odczyt z pliku FillUpStruct("nazwa_pliku_jako_string", types, sizeof(types), "Sekcja2", pointers, sizeof(pointers)); |
Według mnie wygląda to ładnie, i jest proste w użyciu, szczególnie przydatne przy zapisie ustawień np. urządzenia DX.