[m-users.] Dealing with lists of enums as bitflags in C
Julian Fondren
jfondren at minimaltype.com
Tue Jul 9 09:20:02 AEST 2019
On 2019-07-08 17:46, emacstheviking wrote:
> I have been hacking a good hour or two and not really made much
> progress for something that I thought would have been simpler, but.
> Ignorance!!
>
> In my SDL2 wrapper I have a list of types that correspond to the
> various window creation flags, I am passing them as a list as that's
> the nicest way of doing it I think,
>
> sdl_createwindow("Test", 100, 100, 640, 480, [resizable, shown], !IO)
>
> The types are declared as foreign enums in the usual way :-
> :- type window_flag
> ---> fullscreen ; opengl ; shown ; resizable ..... (elided)
>
> :- pragma foreign_enum("C", window_flag/0, [
> fullscreen - "SDL_WINDOW_FULLSCREEN",
> opengl - "SDL_WINDOW_OPENGL",
> shown - "SDL_WINDOW_SHOWN",
> resizable - "SDL_WINDOW_RESIZABLE",
> :...(elided)
> ]).
How's this?
Summary: process the list in Mercury; or the flags in C.
:- module orz.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module string, list.
:- type test
---> test(string, int, int).
main(!IO) :-
foldl((pred(test(T, R, E)::in, !.IO::di, !:IO::uo) is det :-
io.format("flags_to_int(%s) = %d (expected %d)\n",
[s(T), i(R), i(E)], !IO)), Tests, !IO),
Tests = [
test("[]", flags_to_int([]), 0),
test("[fullscreen, opengl]", flags_to_int([fullscreen, opengl]),
3),
test("[...everything...]", flags_to_int(Everything), 15)
],
Everything = [fullscreen, opengl, shown, resizable].
% we want to define these
:- func flags_to_int(list(window_flag)) = int.
:- func or(window_flag, int) = int.
% pretend these constants exist
:- pragma foreign_decl("C", "
#define SDL_WINDOW_FULLSCREEN 1
#define SDL_WINDOW_OPENGL 2
#define SDL_WINDOW_SHOWN 4
#define SDL_WINDOW_RESIZABLE 8
").
% the usual way
:- type window_flag
---> fullscreen ; opengl ; shown ; resizable.
:- pragma foreign_enum("C", window_flag/0, [
fullscreen - "SDL_WINDOW_FULLSCREEN",
opengl - "SDL_WINDOW_OPENGL",
shown - "SDL_WINDOW_SHOWN",
resizable - "SDL_WINDOW_RESIZABLE"
]).
% ------------------------------------------------------------
flags_to_int(L) = foldl(or, L, 0).
:- pragma foreign_proc("C",
or(Flag::in, Acc0::in) = (Acc::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Acc = Acc0 | Flag;
").
More information about the users
mailing list