Odstraňování prvků z datových souprav
#define g_dataset_id_remove_data(l, k) #define g_dataset_remove_data(l, k)
Tyto makra slouží ke zrušení položek soupravy dat napojených na data l. Rušenou položku můžete určit buď číselnou ( GQuark ovou) konstantou k (v případě g_dataset_id_remove_data()) nebo řetězcovým klíčem k (u makra g_dataset_remove_data()). Má-li rušená položka přiřazenou dealokovací funkci, její data se navíc automaticky uvolní z paměti.
Podobně jako v klíčovaných seznamech i u datových souprav máte možnost odstranit položku bez automatického volání dealokovací funkce. Provede se to jedním z následujících dvou způsobů:
void g_dataset_id_remove_no_notify(gconstpointer dataset_location,
GQuark key_id);
#define g_dataset_remove_no_notify(l, k)
Přístupy se opět liší pouze způsobem adresace rušené položky. dataset_location a l je lokace „hlavních“ dat v paměti, key_id GQuark ový klíč a k řetězcový klíč odstraňované položky. I kdyby rušená položka měla asociovánu dealokovací funkci, voláním těchto dvou rutin se proces uvolnění dat nikdy neprovede.
Konstrukce „foreach“
void g_dataset_foreach(gconstpointer dataset_location,
GDataForeachFunc func,
gpointer user_data);
void(*GDataForeachFunc)(GQuark key_id, gpointer data,
gpointer user_data);
Pokud čtete články o knihovně GLib pravidelně, musí vás už (stejně jako mě) dost nudit znovu a znovu číst o funkcích „foreach“. Aby ale tento seriál mohl sloužit také trochu jako referenční příručka, nezbývá mi než poznamenat, že také soupravy dat disponují tímto voláním a ještě jednou zopakovat, jak funkce „foreach“ fungují:
Funkce g_dataset_foreach() zavolá na každý prvek soupravy dat, jejíž rozpoznávacím znakem je pointer dataset_location, uživatelskou funkci func, které předá GQuark ový klíč key_id prvku, jeho data data a uživatelská data user_data. Vykoná se tak něco jako příkaz „pro každou položku soupravy dat udělej __něco__“.
Uvolnění soupravy dat z paměti
void g_dataset_destroy(gconstpointer dataset_location);
…voláním této funkce se souprava dat, která je napojena na dataset_location, uvolní z paměti. Na všechny její prvky budou zavolány (pokud existují) příslušné dealokovací funkce, takže se uvolní i uložená data. S „hlavními“ daty dataset_location se pochopitelně nestane nic – to musíte obstarat sami.
Příklad
Následující příklad simuluje typické použití souprav dat. Sestává ze tří souborů: libclovek.c a libclovek.h je jakási knihovna funkcí pro práci s databází kontaktů (opravdu primitivní – jen pro ukázku). Soubor main.c je pak hlavní program, který tuto knihovnu používá.
/************** Soubor: libclovek.h ***************/
/* struktura definujici jednoho cloveka */
typedef struct {
gchar *jmeno;
gchar *prijmeni;
} LibClovek;
/* deklarace funkce */
extern LibClovek* lib_cti_cloveka(void);
/************** Soubor: libclovek.c ***************/
/* Vnejsi knihovna pracujici s databazi kontaktu */
#include <glib.h>
#include „libclovek.h“
/* Funkce, ktera cte jednoho cloveka z databaze */
LibClovek* lib_cti_cloveka(void)
{
LibClovek *clovek;
clovek = g_malloc(sizeof(LibClovek));
/* Tady by spravne melo byt cteni z databaze.
* Pro jednoduchost vsak promennou clovek jen nejak
* inicializujeme: */
clovek->jmeno = "Karel";
clovek->prijmeni = "Novak";
return clovek;
}
/* Nacteni dalsiho cloveka :-) */
LibClovek* lib_cti_dalsiho_cloveka(void)
{
LibClovek *clovek;
clovek = g_malloc(sizeof(LibClovek));
clovek->jmeno = "Josef";
clovek->prijmeni = "Kvetinac";
return clovek;
}
/**************** Soubor: main.c ******************/
/* Hlavni program */
#include <glib.h>
#include „libclovek.h“
#define ADRESA 1
#define TELEFON 2
gint main(void)
{
LibClovek *clovek, *clovek2;
/* Nacteni cloveka z databaze */
clovek = lib_cti_cloveka();
/* Struktura LibClovek nam nestaci. Chteli bychom u kazdeho
* cloveka uchovavat jeste jeho telefonni cislo a adresu. */
g_dataset_id_set_data(clovek, ADRESA, "Polni 22, Praha 8");
g_dataset_id_set_data(clovek, TELEFON, "02/321321");
/* Nacteni dalsiho cloveka */
clovek2 = lib_cti_dalsiho_cloveka();
g_dataset_id_set_data(clovek2, ADRESA, "Zahradni 1, Liberec");
g_dataset_id_set_data(clovek2, TELEFON, "0386/111222");
/* ... nejake zpracovani ... */
/* Kontrolni tisk */
printf("%s %s, %s; telefon: %s\n",
clovek->jmeno, clovek2->prijmeni,
g_dataset_id_get_data(clovek, ADRESA),
g_dataset_id_get_data(clovek, TELEFON));
printf("%s %s, %s; telefon: %s\n",
clovek2->jmeno, clovek2->prijmeni,
g_dataset_id_get_data(clovek2, ADRESA),
g_dataset_id_get_data(clovek2, TELEFON));
g_dataset_destroy(clovek);
g_dataset_destroy(clovek2);
g_free(clovek);
g_free(clovek2);
}
Soubor libclovek.h definuje strukturu LibClovek jejímiž prvky jsou řetězce jmeno a prijmeni.
Soubor libclovek.c obsahuje dvě funkce, které toho opravdu moc nedělají – slouží jen k demonstraci. V reálném programu by načítaly z databáze jeden záznam a ve struktuře LibClovek jej předávaly jako návratovou hodnotu. Pro naši ukázku stačí, když alokují místo pro jeden záznam a inicializují ho nějakými statickými hodnotami.
Dostáváme k hlavnímu programu, souboru main.c. Jeho úkolem by v reálné situaci bylo nějakým způsobem údaje o lidech zpracovávat. Program využívá knihovnu libclovek, ale struktura LibClovek jeho účelům nestačí. Bylo by třeba u každého záznamu uchovávat ještě nějaké další údaje: třeba adresu a telefonní číslo. Do „standardní“ knihovny libclovek zasahovat nemůžeme, proto použijeme soupravy dat.
Ve zdrojovém kódu můžete vidět, jak se k adrese paměti, kterou uchovávají pointery clovek a clovek2 asociují řetězcové položky s klíči ADRESA a TELEFON.
Následuje kontrolní tisk všech údajů na obrazovku a dealokování veškerých dynamických dat.
V příkladu jsem záměrně nepoužil řetězcové konstanty – dokonce jsem vypustil celý mechanizmus kvarků. Chtěl jsem totiž ukázat, že k použití souprav dat, ale i klíčovaných seznamů dat je vůbec nepotřebujeme. Stačí, když si uvědomíme, že GQuark y nejsou nic jiného než přirozená čísla (1..???). A tak místo řetězců můžeme jednoduše používat konstantní makra (viz ADRESA a TELEFON).
Ukázka by po zkompilování měla vypsat:
Karel Novak, Polni 22, Praha 8; telefon: 02/321321 Josef Kvetinac, Zahradni 1, Liberec; telefon: 0386/111222