Hlavní navigace

GLib: Pole (3)

Michal Burda

Dnešním pokračováním završíme výklad o polích knihovny GLib. Probereme si práci s automaticky rostoucími poli bajtů.

Pole bajtů je speciálním případem polí, definovaných strukturou GArray (viz GLib část 9.). Automaticky rostoucí pole bajtů je definováno strukturou:

struct GByteArray
{
  guint8 *data;
  guint   len;
};

Jako obvykle, data je naše pole bajtů, se kterým se může pracovat jako s obyčejným céčkovským polem, len pak zase aktuální délka pole. Funkce pro práci s GByteArray  jsou analogické s funkcemi pro práci s  GArray (GLib část 9.) či GPtrArray (GLib část 10.), proto dnes jen velice v krátkosti:

Vytvoření pole GByteArray

Nové „nafukovací“ pole bajtů ( GByteArray) se vytvoří zavoláním funkce

GByteArray* g_byte_array_new(void); 

Přidávání položek do pole GByteArray

Pro ukládání položek do pole bajtů slouží následující dvě funkce.

GByteArray* g_byte_array_append(GByteArray *array,
                                const guint8 *data, guint len);

GByteArray* g_byte_array_prepend(GByteArray *array,
                                 const guint8 *data, guint len);

Funkce g_byte_array_append() slouží k přidání položek na konec pole, zatímco g_byte_array_prepend() ukládá prvky na začátek pole (všechny ostatní položky se posunou).

V obou případech platí, že array je cílové pole, data je pointer na pole vkládaných dat (popřípadě pointer na jeden prvek) a len pak počet bajtů, které se mají do pole přidat. Funkce tedy do pole array přidají len bajtů od adresy uložené v pointeru data. Pole array se podle potřeby zvětší.

GByteArray* g_byte_array_set_size(GByteArray *array,
                                  guint length);

…nastaví velikost pole array na hodnotu length. Je-li length větší, než aktuální velikost pole, vytvoří se na konci patřičný počet nových položek. Je-li argument length naopak menší než délka pole array, dojde k oříznutí pole na stanovenou velikost. Nově vytvořené položky se neinicializují, budou tedy mít náhodnou hodnotu.

Odstraňování položek z GByteArray

GByteArray* g_byte_array_remove_index(GByteArray *array,
                                      guint index);

…z pole array odstraní prvek s indexem index. Položky za tímto prvkem se posunou na jeho místo.

Funkce:

GByteArray* g_byte_array_remove_index_fast(GByteArray *array,
                                           guint index);

…je „rychlejší“ variantou funkce g_byte_array_remove_index(). Tato funkce odstraní index-tý prvek pole array tak, že na jeho místo přesune poslední položku. Ušetří se tak čas, protože není nutno přesouvat všechny prvky za tímto indexem o pozici dopředu. Nevýhodou však zůstává nedodržení pořadí prvků v poli.

Odkazování se na položky pole GByteArray

Pro přístup k položkám je dobré používat makro g_array_index(a,t,i), které bylo důkladně popsáno v deváté části. Pro rychlost jen připomenu, že se toto makro rozvine do kódu, ve kterém a znamená zdrojové pole, t typ uložených prvků (v našem případě vždy guint8) a i index požadované položky.

Škoda jen, že tvůrci knihovny GLib zapomněli jaksi pro úplnost dodefinovat makro g_byte_array_index(), které by se pro tento účel používalo. Mohlo by vypadat třeba takto:

#define g_byte_array_index(a,i)   (((guint8*) (a)->data) [(i)])

Uvolnění GByteArray z paměti

void g_byte_array_free(GByteArray *array,
                       gboolean free_segment);

Tato funkce uvolní pole array z paměti. Je-li argument free_segment roven TRUE, dealokuje také veškerá data.

Našli jste v článku chybu?