aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-07-15 02:03:30 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-07-15 02:03:30 +0200
commit2f6bd216d1411bd6ec96eaebf815dc3d5ab5a2f4 (patch)
treef4ab4b455502c558a3c855f0ea7e164b1e246e04
parent095954fe8c0d1a64d8696d0ad0cd0ed395dd6c54 (diff)
downloadEpisodeBrowser-2f6bd216d1411bd6ec96eaebf815dc3d5ab5a2f4.tar.gz
Reimplement Pl with variadic templates
This is a bit safer and about as complex.
-rw-r--r--c/datalistview.cpp5
-rw-r--r--c/defs.h52
-rw-r--r--c/episodelistview.cpp46
-rw-r--r--c/main.cpp44
-rw-r--r--c/pl.cpp135
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;
diff --git a/c/defs.h b/c/defs.h
index 06b1ef1..f57989c 100644
--- a/c/defs.h
+++ b/c/defs.h
@@ -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);
diff --git a/c/main.cpp b/c/main.cpp
index 1d8a981..2ae1c84 100644
--- a/c/main.cpp
+++ b/c/main.cpp
@@ -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;
}
diff --git a/c/pl.cpp b/c/pl.cpp
index 7c86d0d..30b70a9 100644
--- a/c/pl.cpp
+++ b/c/pl.cpp
@@ -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;
}