| 1 | = Chart API = |
| 2 | == Motivace == |
| 3 | 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í;) |
| 4 | |
| 5 | == Jak to funguje == |
| 6 | Je to docela prosté, všechen kód je ve source:forest.c, source: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): |
| 7 | |
| 8 | {{{ |
| 9 | /* |
| 10 | * Type for generic chart-processing function. |
| 11 | */ |
| 12 | typedef void (*ChartFunction) (Value *value, void *argument); |
| 13 | }}} |
| 14 | |
| 15 | K použití se tedy vytvoří funkce tohoto typu a pak se zavolá: |
| 16 | |
| 17 | {{{ |
| 18 | walkChart(myChartFunction, nejakyUkazatel); |
| 19 | }}} |
| 20 | |
| 21 | kde ''myChartFunction'' je nějaká funkce typu !ChartFunction a ''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]. Kromě toho se automaticky při prvním zavolání walkChart() provede zpětná propagace Values ve forestu. |
| 22 | |
| 23 | == Praktická ukázka: tisk chartu z forest of values == |
| 24 | 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. |
| 25 | |
| 26 | {{{ |
| 27 | /* |
| 28 | * Prints chart from forest of values |
| 29 | */ |
| 30 | void print_chart_from_forest(Value *value, void *file) { |
| 31 | print_only_edge((FILE*) file, value->edge); |
| 32 | if (value->value != NULL) { |
| 33 | print_value((FILE*) file, value->value); |
| 34 | } else { |
| 35 | fprintf((FILE*) file, "NULL"); |
| 36 | } |
| 37 | fprintf((FILE*) file, "\n"); |
| 38 | } |
| 39 | |
| 40 | void kp_print_chart (FILE * f, int use_limits) |
| 41 | { |
| 42 | if (cfg.print_chart & 8) {//print from forest of values |
| 43 | walkChart(print_chart_from_forest, f); |
| 44 | } else if (cfg.print_chart & 2) { |
| 45 | print_chart_xref (f, kp_chart); |
| 46 | } else { |
| 47 | print_chart (f, kp_chart); |
| 48 | } |
| 49 | } |
| 50 | }}} |
| 51 | |
| 52 | == Caveat == |
| 53 | |
| 54 | * 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...:) |
| 55 | * '''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. |