= 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.