diff options
author | John Ankarström <john@ankarstrom.se> | 2022-07-15 02:03:30 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-07-15 02:03:30 +0200 |
commit | 2f6bd216d1411bd6ec96eaebf815dc3d5ab5a2f4 (patch) | |
tree | f4ab4b455502c558a3c855f0ea7e164b1e246e04 | |
parent | 095954fe8c0d1a64d8696d0ad0cd0ed395dd6c54 (diff) | |
download | EpisodeBrowser-2f6bd216d1411bd6ec96eaebf815dc3d5ab5a2f4.tar.gz |
Reimplement Pl with variadic templates
This is a bit safer and about as complex.
-rw-r--r-- | c/datalistview.cpp | 5 | ||||
-rw-r--r-- | c/defs.h | 52 | ||||
-rw-r--r-- | c/episodelistview.cpp | 46 | ||||
-rw-r--r-- | c/main.cpp | 44 | ||||
-rw-r--r-- | c/pl.cpp | 135 |
5 files changed, 101 insertions, 181 deletions
diff --git a/c/datalistview.cpp b/c/datalistview.cpp index 661a68e..9c13ae8 100644 --- a/c/datalistview.cpp +++ b/c/datalistview.cpp @@ -34,7 +34,7 @@ void DataListView::ShowEpisode(int iEpisode) lviValue.mask = LVIF_TEXT; term_t t = PL_new_term_refs(3); - if (!Plp(t,"I",iEpisode)) return; + if (!PL_put_integer(t,iEpisode)) return; qid_t q = PL_open_query(NULL, PL_Q_NORMAL, PL_predicate("episode_datum", 3, "episode_data"), t); @@ -43,7 +43,8 @@ void DataListView::ShowEpisode(int iEpisode) char *szValue; TCHAR *tszKey, *tszValue; - if (!Plg(t+1,"ss",&szKey,&szValue)) continue; + if (!(PL_get_atom_chars(t+1,&szKey) && PL_get_atom_chars(t+2,&szValue))) + continue; tszKey = TszFromSz(szKey, CP_UTF8); if (!tszKey) continue; @@ -66,9 +66,55 @@ struct DataListView : public ListView }; /* pl.cpp */ -int Pl(const char *, const char *, const char *, ...); -int Plp(term_t, const char *, ...); -int Plg(term_t, const char *, ...); +int Pl(const char *, const char *); + +inline int PlPut(term_t t, int x) { return PL_put_integer(t, x); } +inline int PlPut(term_t t, long x) { return PL_put_integer(t, x); } +inline int PlPut(term_t t, long long x) { return PL_put_integer(t, x); } +inline int PlPut(term_t t, atom_t x) { return PL_put_atom(t, x); } +inline int PlPut(term_t t, char *x) { return PL_put_atom(t, PL_new_atom(x)); } +inline int PlPut(term_t t, const char *x) { return PL_put_atom(t, PL_new_atom(x)); } +inline int PlPut(term_t t, int *x) { return -1; } +inline int PlPut(term_t t, long *x) { return -1; } +inline int PlPut(term_t t, long long *x) { return -1; } +inline int PlPut(term_t t, atom_t *x) { return -1; } +inline int PlPut(term_t t, char **x) { return -1; } + +inline int PlGet(term_t t, int x) { return -1; } +inline int PlGet(term_t t, long x) { return -1; } +inline int PlGet(term_t t, long long x) { return -1; } +inline int PlGet(term_t t, atom_t x) { return -1; } +inline int PlGet(term_t t, char *x) { return -1; } +inline int PlGet(term_t t, const char *x) { return -1; } +inline int PlGet(term_t t, int *x) { return PL_get_integer(t, x); } +inline int PlGet(term_t t, long *x) { return PL_get_long(t, x); } +inline int PlGet(term_t t, long long *x) { return PL_get_int64(t, x); } +inline int PlGet(term_t t, atom_t *x) { return PL_get_atom(t, x); } +inline int PlGet(term_t t, char **x) { return PL_get_atom_chars(t, x); } + +template <typename T> +int PlPutv(term_t t, T arg) { return PlPut(t, arg); } +template <typename T, typename ...R> +int PlPutv(term_t t, T arg, R... rest) { return PlPut(t, arg)? PlPutv(t+1, rest...): 0; } +template <typename T> +int PlGetv(term_t t, T arg) { return PlGet(t, arg); } +template <typename T, typename ...R> +int PlGetv(term_t t, T arg, R... rest) { return PlGet(t, arg)? PlGetv(t+1, rest...): 0; } +template <typename T> +int Countv(int i, T arg) { return i+1; } +template <typename T, typename ...R> +int Countv(int i, T arg, R... rest) { return Countv(i+1, rest...); } +template <typename ...T> +int Pl(const char *szMod, const char *szPred, T... args) +{ + int iArity = Countv(0, args...); + term_t t = PL_new_term_refs(iArity); + if (!PlPutv(t, args...)) return 0; + if (!PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate(szPred, iArity, szMod), t)) + return 0; + if (!PlGetv(t, args...)) return 0; + return 1; +} /* defs.h */ #ifdef UNICODE diff --git a/c/episodelistview.cpp b/c/episodelistview.cpp index 8273e08..6430b17 100644 --- a/c/episodelistview.cpp +++ b/c/episodelistview.cpp @@ -29,7 +29,7 @@ EpisodeListView::EpisodeListView() : ListView((HMENU)IDC_EPISODELISTVIEW, 0) lvc.cx = Dpi(30); ListView_InsertColumn(m_hWnd, ELVSIRATING, &lvc); - if (!Pl("cfg","get_sort","i",&m_iSort)) + if (!Pl("cfg","get_sort",&m_iSort)) m_iSort = 1; } @@ -63,7 +63,7 @@ LRESULT EpisodeListView::HandleNotify(LPARAM lParam) { int iColumn = lpNmLv->iSubItem+1; m_iSort = abs(m_iSort) == iColumn? -m_iSort: iColumn; - Pl("cfg","set_sort","I",m_iSort); + Pl("cfg","set_sort",m_iSort); DoSort(); ShowFocus(); break; @@ -91,7 +91,7 @@ LRESULT EpisodeListView::HandleNotify(LPARAM lParam) case CDDS_ITEMPREPAINT: { extern HFONT g_fBold; - if (!Pl("track_episodes","watched","I",lpLvCd->nmcd.lItemlParam)) { + if (!Pl("track_episodes","watched",lpLvCd->nmcd.lItemlParam)) { SelectObject(lpLvCd->nmcd.hdc, g_fBold); return CDRF_NEWFONT; } @@ -102,9 +102,9 @@ LRESULT EpisodeListView::HandleNotify(LPARAM lParam) } case NM_DBLCLK: /* Open clicked episode. */ { - if (!Pl("local_episodes","open_episode_locally","I", + if (!Pl("local_episodes","open_episode_locally", m_lviFocus.lParam)) - Pl("local_episodes","open_episode_online","I", + Pl("local_episodes","open_episode_online", m_lviFocus.lParam); break; } @@ -116,9 +116,9 @@ LRESULT EpisodeListView::HandleNotify(LPARAM lParam) while ((lvi.iItem = ListView_GetNextItem( m_hWnd, lvi.iItem, LVNI_SELECTED)) != -1) { if (!ListView_GetItem(m_hWnd, &lvi)) goto b; - if (!Pl("local_episodes","open_episode_locally","I", + if (!Pl("local_episodes","open_episode_locally", lvi.lParam)) - Pl("local_episodes","open_episode_online","I", + Pl("local_episodes","open_episode_online", lvi.lParam); } b: break; @@ -150,7 +150,7 @@ void EpisodeListView::SaveFocus() lvi.mask = LVIF_PARAM; if ((lvi.iItem = ListView_GetNextItem(m_hWnd, -1, LVNI_FOCUSED)) != -1 && ListView_GetItem(m_hWnd, &lvi)) - Pl("cfg","set_focus","I",lvi.lParam); + Pl("cfg","set_focus",lvi.lParam); } void EpisodeListView::SetTop(int iItem) @@ -167,7 +167,7 @@ void EpisodeListView::RestoreFocus() LVFINDINFO lvfi; iItem = 0; - if (!Pl("cfg","get_focus","i",&iEpisode)) return; + if (!Pl("cfg","get_focus",&iEpisode)) return; lvfi.flags = LVFI_PARAM; lvfi.lParam = iEpisode; @@ -214,7 +214,7 @@ void EpisodeListView::SelectUnwatched(int iDir) do { if (!Pl("track_episodes",iDir > 0? "next_unwatched": "previous_unwatched", - "Ii",lvfi.lParam,&iEpNew)) + lvfi.lParam,&iEpNew)) return; lvfi.lParam = iEpNew; @@ -276,23 +276,23 @@ void EpisodeListView::Update() SendMessage(m_hWnd, WM_SETREDRAW, FALSE, 0); ListView_DeleteAllItems(m_hWnd); - if (!Pl("episode_data","ensure_episode_data","")) return; - if (!Pl("episode_data","episode_count","i",&cEp)) return; + if (!Pl("episode_data","ensure_episode_data")) return; + if (!Pl("episode_data","episode_count",&cEp)) return; for (iEp = 1, iItem = 0; iEp <= cEp; iEp++) { extern char g_szLimitScreenwriter[]; extern int g_bViewTVOriginal, g_bViewWatched; if (g_szLimitScreenwriter[0]) - if (!Pl("episode_data","episode_datum","ISS", + if (!Pl("episode_data","episode_datum", iEp,"Screenwriter",g_szLimitScreenwriter)) continue; if (!g_bViewWatched) - if (Pl("track_episodes","watched","I",iEp)) continue; + if (Pl("track_episodes","watched",iEp)) continue; if (!g_bViewTVOriginal) - if (Pl("episode_data","tv_original","I",iEp)) continue; + if (Pl("episode_data","tv_original",iEp)) continue; /* Format episode number string. */ _stprintf_s(tszEpisode, sizeof(tszEpisode), TEXT("%d"), iEp); @@ -358,16 +358,16 @@ void EpisodeListView::UpdateItem(LPLVITEM lpLvi) static TCHAR tszRating[3]; tszName = NULL; - if (!Pl("episode_data","episode_title","Is",lpLvi->lParam,&szName)) { - if (!Pl("episode_data","update_episode_data","")) goto r; - if (!Pl("episode_data","episode_title","Is",lpLvi->lParam,&szName)) + if (!Pl("episode_data","episode_title",lpLvi->lParam,&szName)) { + if (!Pl("episode_data","update_episode_data")) goto r; + if (!Pl("episode_data","episode_title",lpLvi->lParam,&szName)) goto r; } tszName = TszFromSz(szName, CP_UTF8); if (tszName) ListView_SetItemText(m_hWnd, lpLvi->iItem, ELVSITITLE, tszName); -r: if (!Pl("episode_data","episode_rating","Ii",lpLvi->lParam,&iRating)) { +r: if (!Pl("episode_data","episode_rating",lpLvi->lParam,&iRating)) { ListView_SetItemText(m_hWnd, lpLvi->iItem, ELVSIRATING, TEXT("")); goto f; } @@ -423,8 +423,8 @@ int CALLBACK ElvSort(LPARAM iItem1, LPARAM iItem2, LPARAM lExtra) int iRating1, iRating2; iRating1 = lpElv->m_iSort > 0? 99: -1; iRating2 = lpElv->m_iSort > 0? 99: -1; - Pl("episode_data","episode_rating","Ii",lvi1.lParam,&iRating1); - Pl("episode_data","episode_rating","Ii",lvi2.lParam,&iRating2); + Pl("episode_data","episode_rating",lvi1.lParam,&iRating1); + Pl("episode_data","episode_rating",lvi2.lParam,&iRating2); if (iRating1 == iRating2) return Cmp(lvi1.lParam, lvi2.lParam); return iOrder*Cmp(iRating1, iRating2); @@ -433,9 +433,9 @@ int CALLBACK ElvSort(LPARAM iItem1, LPARAM iItem2, LPARAM lExtra) { char *sz1, *sz2; int cch, cch1, cch2; - if (!Pl("episode_data","episode_title","Is",lvi1.lParam,&sz1)) + if (!Pl("episode_data","episode_title",lvi1.lParam,&sz1)) return 0; - if (!Pl("episode_data","episode_title","Is",lvi2.lParam,&sz2)) + if (!Pl("episode_data","episode_title",lvi2.lParam,&sz2)) return 0; cch1 = strlen(sz1); cch2 = strlen(sz2); @@ -110,7 +110,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, ShowWindow(hWnd, nCmdShow); /* Populate episode list view. */ - Pl("track_episodes", "update_tracked_episodes", ""); + Pl("track_episodes", "update_tracked_episodes"); g_lpElv->Update(); g_lpElv->RestoreFocus(); @@ -150,9 +150,9 @@ static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam) /* Get saved view settings. */ char *sz; - Pl("cfg","get_view_watched","i",&g_bViewWatched); - Pl("cfg","get_view_tv_original","i",&g_bViewTVOriginal); - if (Pl("cfg","get_limit_screenwriter","s",&sz)) + Pl("cfg","get_view_watched",&g_bViewWatched); + Pl("cfg","get_view_tv_original",&g_bViewTVOriginal); + if (Pl("cfg","get_limit_screenwriter",&sz)) strcpy_s(g_szLimitScreenwriter, sizeof(g_szLimitScreenwriter), sz); return 0; } @@ -218,7 +218,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WA_ACTIVE: case WA_CLICKACTIVE: SetFocus(g_hFocus); - Pl("track_episodes","update_tracked_episodes",""); + Pl("track_episodes","update_tracked_episodes"); g_lpElv->Redraw(); } break; @@ -236,7 +236,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) /* Animate ellipsis in status bar while doing * work in other thread. */ - if (Pl("episode_data","thread_running","A",g_aThread)) { + if (Pl("episode_data","thread_running",g_aThread)) { i = (i+1)%4; SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)(i==0? TEXT("."): @@ -262,11 +262,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case IDM_FILE_FETCH_DATA: if (g_bThread) break; - Pl("episode_data","thread_create","Sa","update_episode_data",&g_aThread); + Pl("episode_data","thread_create","update_episode_data",&g_aThread); goto t; case IDM_FILE_FETCH_SCREENWRITERS: if (g_bThread) break; - Pl("episode_data","thread_create","Sa","update_screenwriters",&g_aThread); + Pl("episode_data","thread_create","update_screenwriters",&g_aThread); t: KillTimer(hWnd, IDT_TIMER); SetTimer(hWnd, IDT_TIMER, 500, NULL); SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)TEXT(".")); @@ -285,7 +285,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) CheckMenuItem(GetMenu(hWnd), IDM_VIEW_WATCHED, g_bViewWatched? MF_UNCHECKED: MF_CHECKED); g_bViewWatched = !g_bViewWatched; - Pl("cfg","set_view_watched","I",g_bViewWatched); + Pl("cfg","set_view_watched",g_bViewWatched); g_lpElv->Update(); g_lpElv->EnsureFocusVisible(); break; @@ -295,7 +295,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) CheckMenuItem(GetMenu(hWnd), IDM_VIEW_TV_ORIGINAL, g_bViewTVOriginal? MF_UNCHECKED: MF_CHECKED); g_bViewTVOriginal = !g_bViewTVOriginal; - Pl("cfg","set_view_tv_original","I",g_bViewTVOriginal); + Pl("cfg","set_view_tv_original",g_bViewTVOriginal); g_lpElv->Update(); g_lpElv->EnsureFocusVisible(); break; @@ -317,14 +317,14 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (!ListView_GetItem(g_lpElv->HWnd(), &lvi)) break; char *sz; - if (!Pl("episode_data","episode_datum","ISs",lvi.lParam,"Screenwriter",&sz)) + if (!Pl("episode_data","episode_datum",lvi.lParam,"Screenwriter",&sz)) break; strcpy_s(g_szLimitScreenwriter, sizeof(g_szLimitScreenwriter), sz); CheckMenuItem(GetMenu(hWnd), IDM_VIEW_OTHERS, MF_UNCHECKED); } - Pl("cfg","set_limit_screenwriter","S",g_szLimitScreenwriter); + Pl("cfg","set_limit_screenwriter",g_szLimitScreenwriter); g_lpElv->Update(); g_lpElv->EnsureFocusVisible(); break; @@ -361,28 +361,28 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) switch (LOWORD(wParam)) { case IDM_WATCH_LOCALLY: - Pl("local_episode","open_episode_locally","I",lvi.lParam); + Pl("local_episode","open_episode_locally",lvi.lParam); break; case IDM_WATCH_ONLINE: - Pl("local_episode","open_episode_online","I",lvi.lParam); + Pl("local_episode","open_episode_online",lvi.lParam); break; case IDM_TOGGLE: - Pl("track_episodes","toggle_episode","I",lvi.lParam); + Pl("track_episodes","toggle_episode",lvi.lParam); g_lpElv->Redraw(); break; case IDM_FORGET: - Pl("track_episodes","forget_episode","I",lvi.lParam); - Pl("track_episodes","update_tracked_episodes",""); + Pl("track_episodes","forget_episode",lvi.lParam); + Pl("track_episodes","update_tracked_episodes"); g_lpElv->Redraw(); break; case IDM_LOOKUP: - Pl("episode_data","retract_episode","I",lvi.lParam); + Pl("episode_data","retract_episode",lvi.lParam); g_lpElv->UpdateItem(&lvi); g_lpElv->Redraw(); g_lpDlv->ShowEpisode(lvi.lParam); break; case IDM_WIKI: - Pl("episode_data","open_episode_wiki","I",lvi.lParam); + Pl("episode_data","open_episode_wiki",lvi.lParam); break; case IDM_RATE10: iRating = 10; @@ -416,7 +416,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) goto r; case IDM_RATE0: iRating = 0; - r: Pl("episode_data","rate_episode","II",lvi.lParam,iRating); + r: Pl("episode_data","rate_episode",lvi.lParam,iRating); g_lpElv->UpdateItem(&lvi); break; } @@ -489,8 +489,8 @@ HWND CreateStatusBar(HWND hWndParent, HINSTANCE hInstance) /* Attach persistent databases. */ int Attach() { - if (!Pl("track_episodes","attach","")) return 0; - if (!Pl("episode_data","attach","")) return 0; + if (!Pl("track_episodes","attach")) return 0; + if (!Pl("episode_data","attach")) return 0; return 1; } @@ -1,136 +1,9 @@ -#include <stdarg.h> -#include <string.h> #include <SWI-Prolog.h> -#include "defs.h" -static int Plpv(term_t, const char *, va_list); -static int Plgv(term_t, const char *, va_list); - -/* Call Prolog predicate once. */ -int Pl(const char *szMod, const char *szPred, const char *szFmt, ...) -{ - int iArity; - term_t t; - va_list vl, vl2; - - iArity = strlen(szFmt); - t = PL_new_term_refs(iArity); - - va_start(vl, szFmt); - va_copy(vl2, vl); - - if (!Plpv(t, szFmt, vl)) goto f; - if (!PL_call_predicate(NULL, PL_Q_NORMAL, - PL_predicate(szPred, iArity, szMod), t)) - goto f; - if (!Plgv(t, szFmt, vl2)) goto f; - - va_end(vl); - va_end(vl2); - return 1; -f: va_end(vl); - va_end(vl2); - return 0; -} - -/* Put known values in term. */ -int Plp(term_t t, const char *szFmt, ...) -{ - int r; - va_list vl; - va_start(vl, szFmt); - r = Plpv(t, szFmt, vl); - va_end(vl); - return r; -} -int Plpv(term_t t, const char *szFmt, va_list vl) -{ - int i; - for (i = 0; szFmt[i]; i++) { - switch (szFmt[i]) { - case 'I': - { - int x; - x = va_arg(vl, int); - if (!PL_put_integer(t+i, x)) return 0; - break; - } - case 'A': - { - atom_t x; - x = va_arg(vl, atom_t); - if (!PL_put_atom(t+i, x)) return 0; - break; - } - case 'S': - { - atom_t a; - char *x; - x = va_arg(vl, char *); - a = PL_new_atom(x); - if (!PL_put_atom(t+i, a)) return 0; - break; - } - case 'i': - va_arg(vl, int *); - break; - case 'a': - va_arg(vl, atom_t *); - break; - case 's': - va_arg(vl, char **); - break; - } - } - return 1; -} - -/* Get unknown values from term. */ -int Plg(term_t t, const char *szFmt, ...) -{ - int r; - va_list vl; - va_start(vl, szFmt); - r = Plgv(t, szFmt, vl); - va_end(vl); - return r; -} -int Plgv(term_t t, const char *szFmt, va_list vl) +int Pl(const char *szMod, const char *szPred) { - int i; - for (i = 0; szFmt[i]; i++) { - switch (szFmt[i]) { - case 'i': - { - int *lp; - lp = va_arg(vl, int *); - if (!PL_get_integer(t+i, lp)) return 0; - break; - } - case 'a': - { - atom_t *lp; - lp = va_arg(vl, atom_t *); - if (!PL_get_atom(t+i, lp)) return 0; - break; - } - case 's': - { - char **lp; - lp = va_arg(vl, char **); - if (!PL_get_atom_chars(t+i, lp)) return 0; - break; - } - case 'I': - va_arg(vl, int); - break; - case 'A': - va_arg(vl, atom_t); - break; - case 'S': - va_arg(vl, char *); - break; - } - } + term_t t = PL_new_term_refs(0); + if (!PL_call_predicate(NULL, PL_Q_NORMAL, PL_predicate(szPred, 0, szMod), t)) + return 0; return 1; } |