wiki:ChartAPI

Chart API

Motivace

Když jsem začal dělat vypisování chartu podle forest of values (viz #29), zjistil jsem, že můžu směle zkopírovat x desítek řádků kódu, co jsem používal pro extrakci struktur, a téměř polovinu souboru extras.c, pokud jsem chtěl, aby se nejprve provedla zpětná propagace values. To se mi vůbec nelíbilo, takhle úděsná duplikace kódu se někdy v budoucnu dokáže dost vymstít. A když jsem nad tím pak dál přemýšlel, tak mě napadlo, jestli nebude lepší vytáhnout všechen tenhle kód někam bokem a udělat k němu nějaké miniaturní rozhraní. Jsem si vědom toho, že říkat tomu Chart API je hodně nadnesené, ale nějak se to jmenovat musí;)

Jak to funguje

Je to docela prosté, všechen kód je ve source:trunk/forest.c, source:trunk/forest.h. Stará se o to, že efektivně projde forest of values (= do šířky s kontrolou opakování, nezapomene na různé "díry" apod.) a na každou Value v chartu/forestu zavolá uživatelskou funkci typu ChartFunction, která bere za argument právě tu Value a volitelně další parametr (pointer na cokoli):

/*
 * Type for generic chart-processing function.
 */
typedef void (*ChartFunction) (Value *value, void *argument);

K použití se tedy vytvoří funkce tohoto typu a pak se zavolá:

walkChart(myChartFunction, 1, nejakyUkazatel);

kde myChartFunction je nějaká funkce typu ChartFunction, druhý argument (0/1) určuje, zda-li se má provést zpětná propagace a prořezání morfologických hodnot a (volitelně, default NULL) nejakyUkazatel je ukazatel, který se vždy předá myChartFunction společně s Value. Protože to je ukazatel na cokoli, dá se takhle předat třeba i pole apod. Implementace toho všeho je v podstatě celý changeset [489].

Praktická ukázka: tisk chartu z forest of values

Verba movent, exempla trahunt, takhle vypadá použití pro tisk chartu z forest of values, obdobně je na to teď navázaná i ta extrakce struktur (možná by šla takhle udělat i beautifyizace chartu? Nejsem si jistý ani jestli by to šlo, ani jestli to má smysl -- spíš ne -- leda že by se nějak využilo to prořezání hodnot). Jako volitelný argument se tu předává výstupní file descriptor.

/*
 * Prints chart from forest of values
 */
void print_chart_from_forest(Value *value, void *file) {
    print_only_edge((FILE*) file, value->edge);
    if (value->value != NULL) {
      print_value((FILE*) file, value->value);
    } else {
      fprintf((FILE*) file, "NULL");
    }
    fprintf((FILE*) file, "\n");
}

void kp_print_chart (FILE * f, int use_limits)
{
    if (cfg.print_chart & 8) {//print from forest of values
        walkChart(print_chart_from_forest, f);
    } else if (cfg.print_chart & 2) {
        print_chart_xref (f, kp_chart);
    } else {
        print_chart (f, kp_chart);
    }
}

Caveat

  • snažil jsem se to docela otestovat, tj. např. ověřit jestli ta extrakce funguje tak jak předtím, ale těch změn v kódu bylo docela dost, takže...:)
  • vůbec netuším, jestli to celé není nesmyslná hovadina, možná se ukáže, že to k ničemu není a je to blbost! I v tom případě mám ale pocit, že současná podoba je lepší, než kdybych kopíroval hafo kódu jen kvůli tomu tisku a extrakci.
Last modified 15 years ago Last modified on Feb 5, 2009, 8:31:34 PM