Hlavní navigace

GLib: Užitečnosti všeho druhu

10. 5. 2001
Doba čtení: 5 minut

Sdílet

V dnešním pokračovaní si ukážeme sadu funkcí těžko zařaditelnou do nějaké konkrétní skupiny. Zkrátka a dobře, jsou to různé rutiny, které se občas hodí. Knihovna GLib garantuje, že jsou přenositelné i na jiné platformy, a to je jistě příjemné.

Zjištění verze knihovny GLib

Verze knihovny GLib je zaznamenaná ve trojici maker:

#define GLIB_MAJOR_VERSION
#define GLIB_MINOR_VERSION
#define GLIB_MICRO_VERSION

Každé makro znamená jednu složku čísla verze knihovny:

GLib version  1. 2. 8
              |  |  |
          |  |  V
          |  V  GLIB_MICRO_VERSION
          V  GLIB_MINOR_VERSION
          GLIB_MAJOR_VERSION

Ve svých programech je můžete využít třeba k výpisu informace o verzi, pod kterou byla aplikace zkompilována.

Chcete-li naopak zkontrolovat, je-li program sestavován pod vámi požadovanou verzí knihovny, můžete s úspěchem využít následující makro:

#define GLIB_CHECK_VERSION(major,minor,micro)

Makro vrátí TRUE, je-li aktuální verze knihovny stejná nebo lepší než zadaná verze major. minor. micro.

Oddělovače

Nepříjemnost s různými oddělovači adresářů na různých platformách řeší následující konstantní makra:

#define G_DIR_SEPARATOR
#define G_DIR_SEPARATOR_S

G_DIR_SEPARATOR je na Unixech roven '/' a ve Windows '\'. V makru G_DIR_SEPARATOR_S je definováno totéž, ale jako řetězec (tedy "/""\").

Podobně se věci mají i u těchto maker:

#define G_SEARCHPATH_SEPARATOR
#define G_SEARCHPATH_SEPARATOR_S

G_SEARCHPATH_SEPARATOR uchovává oddělovač cest v proměnné prostředí PATH. V Unixu je to dvojtečka ( ':') a ve Windows středník ( ';'). Potřebujete-li oddělovač cest zapsaný jako řetězec, sáhněte po  G_SEARCHPATH_SEPARATOR_S.

Boolovské hodnoty

V dřívějších dílech jsem běžně v příkladech používal boolovské konstanty TRUE a FALSE (což není standardní výbava jazyka C), aniž bych se předtím zmínil o tom, že jsou definovány v knihovně GLib. Za to se všem omlouvám a jen pro pořádek uvádím jejich definici:

#define FALSE (0)
#define TRUE  (!FALSE)

Stejně tak makro

#define NULL ((void*) 0)

…označující prázdný ( NULL ový) pointer.

Větší, menší

#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))

…jednoduchá makra, jejichž výsledkem je menší (větší) číslo z a  a b.

Výpočet absolutní hodnoty je realizován makrem:

#define ABS(a) (((a) < 0) ? -(a) : (a))

Pro zarovnání hodnoty do číselného intervalu slouží makro:

#define CLAMP(x, low, high) \
    (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))

Jeho výsledkem je zadané číslo x, pokud se nachází v rozmezí hodnot low a high. Je-li x menší, vrátí se low, je-li větší, předá se high.

Například výsledkem všech tří následujících volání bude číslo  10:

CLAMP(5, 10, 15)
CLAMP(10, 5, 20)
CLAMP(25, 5, 10)

Struktury na úrovni bajtů

#define G_STRUCT_OFFSET(struct_type, member)

…vrátí offset v bajtech položky member struktury struct_type. Argument struct_type je tedy název datového typu struktury (např. GString) a member název položky, jejíž adresový offset chceme získat (např.  len).

#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset)

…zpřístupní v konkrétní instanci struktury, na níž ukazuje pointer struct_p, položku s offsetem struct_offset a výsledek přetypuje na typ  member_type.

#define G_STRUCT_MEMBER_P(struct_p, struct_offset)

…vrátí beztypový Pointer na položku s offsetem struct_offset struktury struct_p.

Příklad:

#include <glib.h>

typedef struct {
  char *nazev;
  float max_rychlost;
  float spotreba;
} Automobil;


int main(void) {
  Automobil auto1 = { "Skoda", 130, 7.2 };
  Automobil auto2 = { "Audi", 220, 10.4 };
  
  gulong o_nazev = G_STRUCT_OFFSET(Automobil, nazev);
  gulong o_spotreba = G_STRUCT_OFFSET(Automobil, spotreba);

  printf("%s ma spotrebu %0.1f litru\n",
      G_STRUCT_MEMBER(char*, &auto1, o_nazev),
      G_STRUCT_MEMBER(float, &auto1, o_spotreba));

  printf("%s ma spotrebu %0.1f litru\n",
      G_STRUCT_MEMBER(char*, &auto2, o_nazev),
      G_STRUCT_MEMBER(float, &auto2, o_spotreba));

  return 0;
}

Tato ukázka vypíše na terminál:

Skoda ma spotrebu 7.2 litru
Audi ma spotrebu 10.4 litru

Cesty a jména

gchar* g_get_prgname(void);

…vrátí jméno programového souboru. Pokud používáte knihovnu GDK nebo GTK, je jméno programu inicializováno automaticky ve funkci gdk_init(), která je volána z funkce gtk_init(). Název se zjistí z poslední složky řetězce argv[0]. Jestliže ale výše zmiňované knihovny nepoužíváte a přesto máte pro funkci g_get_prgname() uplatnění, musíte název programu inicializovat sami:

void g_set_prgname(const gchar *prgname);

Na původu řetězce prgname nezáleží, protože rutina si pro název programu alokuje nový řetězec.

Pro získání hodnoty proměnné prostředí poskytuje GLib přenositelnou­ funkci

gchar* g_getenv(const gchar *variable);

Argument variable je název proměnné prostředí a navrácený řetězec je její hodnota, nebo NULL, pokud taková proměnná není definována. Pozn.: ve Windows je vrácený řetězec platný jen do dalšího volání  g_getenv().

Funkce

gchar* g_get_user_name(void);

…vrátí jméno (login) aktuálního uživatele. Pokud na dané platformě není možné jméno zjistit, funkce vrátí řetězec  "somebody".

Podobně tak funkce

gchar* g_get_real_name(void);

…vracející skutečné jméno uživatele (viz. /etc/passwd). Pokud nelze zjistit, vrátí se  "Unknown".

Domácí adresář uživatele, adresář pro dočasné soubory (tmp, temp) a aktuální adresář zjistíte pomocí funkcí:

gchar* g_get_home_dir(void);
gchar* g_get_tmp_dir(void);
gchar* g_get_current_dir(void);

Funkce hledají zmíněné informace v proměnných prostředí HOME (ve Windows NT i HOMEDRIVE  a HOMEPATH), TMPDIR, TMPTEMP

Další práce s cestami k souborům

gchar* g_basename(const gchar *file_name);

…vrátí jméno souboru bez předcházející adresářové složky. Vrácený řetězcový pointer ukazuje přímo doprostřed argumentu file_name.

gchar* g_dirname(const gchar *file_name);

…vrátí adresářovou složku jména souboru file_name. Pokud file_name neobsahuje cestu i s adresáři, použije se jako návratová hodnota řetězec ".". Vrácená hodnota by měla být po použití dealokována.

gboolean g_path_is_absolute(const gchar *file_name);

…vrátí TRUE, jestliže je jméno souboru file_name absolutní, tj. rozhodne, jestli obsahuje plnou cestu z kořenového adresáře. (Např. „ /usr/local“ v Unixech nebo „ C:\WINDOWS\SYSTEM“ ve Windows.)

gchar* g_path_skip_root(gchar *file_name);

CS24_early

…vrátí pointer na jméno souboru file_name těsně za označením kořenového adresáře, tj. za lomítkem ( /) v Unixech a za C:\ ve Windows. Jestliže file_name není absolutní jméno souboru, funkce předá  NULL.

Pokračování příště.

Byl pro vás článek přínosný?

Autor článku

Michal Burda vystudoval informatiku a aplikovanou matematiku a nyní pracuje na Ostravské univerzitě jako odborný asistent. Zajímá se o data mining, Javu a Linux.