GMemChunk
y jsou jistě v mnoha případech užitečné. Jejich problém však spočívá v tom, že všechny prvky (atomy) musí být stejné velikosti. Tím se vylučuje použití Chunků při práci s řetězci, protože každý řetězec může být obecně proměnné délky.
Tento nedostatek vyplňuje knihovna GLib funkcemi kolem datového typu GStringChunk
. Než se pustíme do dalšího výkladu, připomeňme jen v krátkosti použitou terminologii. „Chunkem“ nazývám úsek paměti, skládající se z několika bloků stejné velikosti. Do něj se pak místo alokace dynamicky umisťují nové proměnné, prvky Chunku zvané „atomy“ (viz. předchozí díl).
GStringChunk
GStringChunk
Do GStringChunk
u je možno přidávat řetězce různé délky. Není však možno jednotlivé řetězce z Chunku dealokovat – musíte dealokovat vždy celý GStringChunk
.
Struktura:
struct GStringChunk;
reprezentuje řetězcový Chunk. Práce s ní by měla být realizována výhradně následujícími funkcemi.
GStringChunk* g_string_chunk_new(gint size);
…vytvoří nový GStringChunk
a vrátí pointer na něj. Argument size
je implicitní velikost bloku. Je-li třeba do GStringChunk
u uložit řetězec delší než tato implicitní hodnota, bude pro něj alokován větší blok paměti.
Pro vkládání (neboli kopírování) řetězců do chunku slouží dvě funkce:
gchar* g_string_chunk_insert(GStringChunk *chunk, const gchar *string);
a
gchar* g_string_chunk_insert_const(GStringChunk *chunk, const gchar *string);
Funkce g_string_chunk_insert()
přidá kopii řetězce string
do GStringChunk
u chunk
. Vrátí pointer na tuto kopii. Znaky vráceného řetězce mohou být měněny. Neměli byste však, jako obvykle, zapisovat za konec tohoto řetězce.
Oproti ní, funkce g_string_chunk_insert_const()
nejprve prohledá GStringChunk
chunk
na výskyt řetězce string
. Nalezne-li takový, a byl-li do chunk
u navíc přidán právě funkcí g_string_chunk_insert_const()
, vrátí pointer na něj. Jinak string
do chunk
u zkopíruje a vrátí pointer. Tato funkce je užitečná v případech, kdy hodláte do GStringChunk
u přidávat mnoho konstantních řetězců a nechcete příliš plýtvat místem. Budete-li používat výhradně g_string_chunk_insert_const()
, vloží se každý řetězec do GStringChunk
u pouze jednou – v dalších pokusech se bude vracet pouze pointer na tento již uložený řetězec. Na to však musíte pamatovat. V programu se může vyskytovat několik pointerů na jeden řetězec – jakýkoliv zápis do takového řetězce musí být potom proveden velmi opatrně.
Je třeba poznamenat, že g_string_chunk_insert_const()
nikdy nevrátí pointer na řetězec, který byl do GStringChunk
u přidán funkcí g_string_chunk_insert()
, i kdyby se shodovaly.
g_string_chunk_insert()
void g_string_chunk_free(GStringChunk *chunk);
…uvolní veškerou paměť alokovanou GStringChunk
em chunk
. Po vykonání této funkce již není bezpečné přistupovat k řetězcům, které původně obsahovala.
Příklad:
/* ukazka pouziti GStringChunk */
#include<glib.h>
gint main(void) { GStringChunk *chunk; gchar *s1, *s2, *s3; /* vytvoreni noveho chunku */ chunk = g_string_chunk_new(50); /* vkladani retezcu do chunku */ s1 = g_string_chunk_insert(chunk, RETEZEC); s2 = g_string_chunk_insert_const(chunk, RETEZEC); s3 = g_string_chunk_insert_const(chunk, RETEZEC); /* Po techto operacich budou v chunku dva retezce "Ahoj svete!" */ /* Na prvni bude ukazovat s1 a na druhy s2 a s3 spolecne (viz */ /* nasledujici vypis adres) */ printf("Adresa s1: %p\nAdresa s2: %p\nAdresa s3: %p\n", s1, s2, s3); /* uvolneni GStringChunku z pameti */ g_string_chunk_free(chunk); return(0); }
Po spuštění tohoto ukázkového programu by se měly vypsat adresy tří řetězců uložených do chunku. Adresa prvního řetězce by se měla od ostatních dvou lišit; adresy druhého a třetího řetězce však musí být stejné. Jak je to možné?
Všechny tři řetězce obsahují stejný text definovaný makrem RETEZEC
. První řetězec, s1
, se do chunku přidává jako první a navíc funkcí g_string_chunk_insert()
– kopírování jistě proběhne.
Po něm se alokuje řetězec s2
, ovšem funkcí g_string_chunk_insert_const()
– provede se prohledání chunku na řetězec RETEZEC
, ale bezvýsledně: žádný takový do chunku funkcí g_string_chunk_insert_const()
ještě přidán nebyl (je lhostejné, že už tam ve skutečnosti je alokovaný funkcí g_string_chunk_insert()
).
Nakonec se alokuje řetězec s3
. Voláním funkce g_string_chunk_insert_const()
se znovu prohledá celý chunk – tentokrát se však nalezne řetězec s2
. Funkce tento pointer vrátí – s3
tedy bude ukazovat na fyzicky stejný řetězec jako s2