Prolog "spin"

Admin User, created Apr 17. 2025
         
/**
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
*
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
*
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
*
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
:- ensure_loaded(library(util/charsio)).
/*******************************************************************/
/* HTTP Server */
/*******************************************************************/
/**
* http_server_new(M):
* The predicate succeeds in M with a new http server.
*/
% http_server_new(-Map)
http_server_new(Map) :-
ir_object_new(Map),
os_http_server_new(Server),
ir_object_set(Map, 'server', Server),
ir_object_set(Map, 'state', 0).
/**
* http_server_on(M, T, L, G):
* The predicate succeeds. As a side effect it adds a type T stackfull event
* handler with formal paramaters L and callback goal G to the HTTP server M.
**/
% http_server_on(+Map, +Atom, +List, +Goal)
http_server_on(Map, _, _, _) :-
(ir_object_current(Map, 'state', 1); ir_object_current(Map, 'state', 2)),
throw(error(resource_error(state_error),_)).
http_server_on(Map, Type, Paras, Goal) :-
ir_object_current(Map, 'server', Server),
Head =.. [''|Paras],
sys_frost_horn((Head :- Goal), Native),
os_http_server_on(Server, Type, Native).
/**
* http_server_listen(M, P):
* The predicate succeeds. As a side effect the server M
* starts listening on port P.
*/
% http_server_listen(+Map, +Integer)
http_server_listen(Map, _) :-
(ir_object_current(Map, 'state', 1); ir_object_current(Map, 'state', 2)),
throw(error(resource_error(state_error),_)).
http_server_listen(Map, Port) :-
ir_object_current(Map, 'server', Server),
sys_http_server_listen(Server, Port),
ir_object_set(Map, 'state', 1).
% sys_http_server_listen(+Server, +Integer)
sys_http_server_listen(Server, Port) :- current_prolog_flag(state_async, on), !,
os_http_listen_promise(Server, Port, Q),
'$YIELD'(Q).
sys_http_server_listen(Server, Port) :-
os_http_listen_sync(Server, Port).
/**
* http_server_close(M):
* The predicate succeeds. As a side effect the server M is closed.
*/
http_server_close(Map) :-
ir_object_current(Map, 'state', 2),
throw(error(resource_error(state_error),_)).
http_server_close(Map) :-
ir_object_current(Map, 'state', 0), !,
ir_object_set(Map, 'state', 2).
http_server_close(Map) :-
ir_object_current(Map, 'server', Server),
sys_http_server_close(Server),
ir_object_set(Map, 'state', 2).
% sys_http_server_close(+Server)
sys_http_server_close(Server) :- current_prolog_flag(state_async, on), !,
os_http_close_promise(Server, Q),
'$YIELD'(Q).
sys_http_server_close(Server) :-
os_http_close_sync(Server).
/*******************************************************************/
/* HTTP Request */
/*******************************************************************/
/**
* url_search_params(U, P, L):
* The predicate succeeds in P with the non-query part of U and
* in L with the query part of U decoded into a key-value list.
*/
% url_search_params(+Atom, -Atom, -List)
url_search_params(Url, Path2, List) :-
sub_atom(Url, Pos, _, Pos2, '?'), !,
sub_atom(Url, 0, Pos, _, Path),
sub_atom(Url, _, Pos2, 0, Query),
percent_encode(Path2, Path),
url_search_params_query(Query, List).
url_search_params(Url, Url2, []) :-
percent_encode(Url2, Url).
% url_search_params_query(+Atom, -List)
url_search_params_query(Query, [Pair|List]) :-
sub_atom(Query, Pos, _, Pos2, '&'), !,
sub_atom(Query, 0, Pos, _, Component),
sub_atom(Query, _, Pos2, 0, Rest),
url_search_params_pair(Component, Pair),
url_search_params_query(Rest, List).
url_search_params_query(Query, [Pair]) :-
url_search_params_pair(Query, Pair).
% url_search_params_pair(+Atom, -Pair)
url_search_params_pair(Component, Key2-Value2) :-
sub_atom(Component, Pos, _, Pos2, '='), !,
sub_atom(Component, 0, Pos, _, Key),
sub_atom(Component, _, Pos2, 0, Value),
percent_encode(Key2, Key),
percent_encode(Value2, Value).
url_search_params_pair(Component, Component2-'') :-
percent_encode(Component2, Component).
/**
* http_current_headers(S, M):
* The predicate succeeds in M with the headers of the HTTP request S.
*/
% http_current_headers(+Request, -Map)
http_current_headers(S, M) :-
os_http_current_headers(S, H),
sys_header_results(H, M).
/**
* http_input_new(S, R):
* http_input_new(S, R, O):
* The predicate succeeds in R with a new text reader for the
* HTTP request S. The ternary predicate allows specifying
* text reader options.
*/
% http_input_new(+Request, -Stream)
http_input_new(S, W) :-
sys_http_input_new(S, 0rNone, W).
% http_input_new(+Request, -Stream, +List)
http_input_new(S, W, O) :-
ir_object_new(Map),
sys_stream_opts(O, Map),
sys_http_input_new(S, Map, W).
% sys_http_input_new(+Request, +Map, -Stream)
sys_http_input_new(S, Map, R) :- current_prolog_flag(read_async, on), !,
os_http_input_promise_opts(S, Map, R, Q),
'$YIELD'(Q).
sys_http_input_new(S, Map, R) :-
os_http_input_sync_opts(S, Map, R).
/*******************************************************************/
/* HTTP Response */
/*******************************************************************/
/**
* http_write_head(S, C, H):
* The predicate succeeds. As a side effect it writes the status
* code C and the headers map H to the HTTP response S.
*/
% http_write_head(+Response, +Integer, +List)
http_write_head(Res, Code, List) :-
ir_object_new(Map),
sys_header_opts(List, Map),
os_http_write_head(Res, Code, Map).
/**
* http_output_new(S, W):
* http_output_new(S, W, O):
* The predicate succeeds in W with a new text writer for the
* HTTP response S. The ternary predicate allows specifying
* text writer options.
*/
% http_output_new(+Response, -Stream)
http_output_new(S, W) :-
os_http_output_opts(S, 0rNone, W).
% http_output_new(+Response, -Stream, +List)
http_output_new(S, W, O) :-
ir_object_new(Map),
sys_stream_opts(O, Map),
os_http_output_opts(S, Map, W).
/*******************************************************************/
/* Foreign Predicates */
/*******************************************************************/
% os_http_server_new(F)
% defined in foreign(misc/httplib)
% os_http_server_on(F, C)
% defined in foreign(misc/httplib)
% os_http_listen_sync(F, P)
% defined in foreign(misc/httplib)
% os_http_listen_promise(F, P, Q)
% defined in foreign(misc/httplib)
% os_http_close_sync(F)
% defined in foreign(misc/httplib)
% os_http_close_promise(F, Q)
% defined in foreign(misc/httplib)
% http_current_method(F, G)
% defined in foreign(misc/httplib)
% http_current_path(F, G)
% defined in foreign(misc/httplib)
% os_http_current_headers(F, G)
% defined in foreign(misc/httplib)
% os_http_write_head(F, G, H)
% defined in foreign(misc/httplib)
% os_http_output_opts(F, G, H)
% defined in foreign(misc/httplib)
% os_http_input_promise_opts(F, G, H, I)
% defined in foreign(misc/httplib)
:- ensure_loaded(foreign(misc/httplib)).