9:- module(resp,[resp_write/2, resp_parse/2]). 10
11unicode_size(Char,Size) :-
12 \+ integer(Char),
13 char_code(Char,Code),
14 unicode_size(Code,Size),
15 !.
16unicode_size(0,0).
17unicode_size(Code,1) :- Code =< 127.
18unicode_size(Code,2) :- Code > 127 , Code =< 2047.
19unicode_size(Code,3) :- Code > 2047 , Code =< 65535.
20unicode_size(Code,4) :- Code > 65535 , Code =< 1114111.
21
22unicode_byte_length(String,Length) :-
23 string_codes(String,Codes),
24 unicode_byte_length_list(Codes,Length).
25
26unicode_byte_length_list([],0) :- !.
27unicode_byte_length_list([Code|Codes],Length) :-
28 unicode_size(Code,L0),
29 unicode_byte_length_list(Codes,L),
30 Length is L0 + L.
31
32get_chars(_,[],0) :- !.
33get_chars(Stream,[First|Rest],Count) :-
34 get_char(Stream,First),
35 unicode_size(First,SS),
36 C is Count - SS,
37 get_chars(Stream,Rest,C),
38 !.
45resp_write(Stream,Array) :-
46 resp_write(Stream,Array,false).
47
48resp_write(_,[],true) :-
49 !.
50
51resp_write(Stream,[],_) :-
52 format(Stream,"*0~w",["\r\n"]),
53 !.
54resp_write(Stream,[nil],_) :-
55 format(Stream,"*-1~w",["\r\n"]),
56 !.
57resp_write(Stream,[First|Rest],IsFirst) :-
58 is_list([First|Rest]),
59 length([First|Rest],Length),
60 ( IsFirst == true ;
61 format(Stream,"*~w~w",[Length,"\r\n"])),
62 resp_write_one(Stream,First),
63 resp_write(Stream,Rest,true),
64 !.
65resp_write(Stream,Term,_) :-
66 resp_write_one(Stream,Term),
67 !.
68
69resp_write_one(Stream,string(String)) :-
70 format(Stream,"+~w~w",[String,"\r\n"]).
71resp_write_one(Stream,error(String)) :-
72 format(Stream,"-~w~w",[String,"\r\n"]).
73resp_write_one(Stream,integer(String)) :-
74 format(Stream,":~w~w",[String,"\r\n"]).
75resp_write_one(Stream,bulk(nil)) :-
76 format(Stream,"$~w~w",["-1","\r\n"]).
77resp_write_one(Stream,bulk(String)) :-
78 unicode_byte_length(String,Length),
79 format(Stream,"$~w~w~w~w",[Length,"\r\n",String,"\r\n"]).
80resp_write_one(Stream,Array) :-
81 is_list(Array),
82 resp_write(Stream,Array).
83
84resp_writef_array(Stream,Array) :-
85 format(Stream,"~w",[Array]).
86
87resp_write_one_array([],"") :- !.
88resp_write_one_array([First|Rest],ResultString) :-
89 new_memory_file(MF),
90 open_memory_file(MF, write, Stream),
91 resp_write_one(Stream,First),
92 close(Stream),
93 memory_file_to_string(MF,FirstResult,utf8),
94 free_memory_file(MF),
95 resp_write_one_array(Rest,ResultRest),
96 swritef(ResultString,"%w%w",[FirstResult,ResultRest]).
102resp_parse(Stream,Result) :-
103 read_line_to_codes(Stream,[TypeCode|ArgumentCodes]),
104 char_code(Type,TypeCode),
105 atom_chars(Arguments,ArgumentCodes),
106 resp_parse(Type,Arguments,Stream,Result).
107 108resp_parse(_,[]) :- !.
109
110resp_parse('+',Argument,_,string(Argument)) :- !.
111resp_parse(':',Argument,_,integer(ArgumentInteger)) :-
112 atom_number(Argument,ArgumentInteger),
113 !.
114resp_parse('-',Argument,_,error(Argument)) :- !.
115resp_parse('$',Argument,_,bulk(nil)) :-
116 atom_number(Argument,Count),
117 Count < 0,
118 !.
119resp_parse('$',Argument,Stream,bulk(Result)) :-
120 atom_number(Argument,Count),
121 get_chars(Stream,ResultChars,Count),
122 string_codes(Result,ResultChars),
123 get_code(Stream,_),
124 get_code(Stream,_),
125 !.
126resp_parse('*',Argument,Stream,Result) :-
127 atom_number(Argument,Count),
128 resp_parse_array(Stream,Count,Result),
129 !.
130
131resp_parse_array(_,-1,[nil]) :- !.
132resp_parse_array(_,0,[]) :- !.
133resp_parse_array(Stream,Count,[First|Rest]) :-
134 read_line_to_codes(Stream,[TypeCode|ArgumentCodes]),
135 char_code(Type,TypeCode),
136 atom_chars(Arguments,ArgumentCodes),
137 resp_parse(Type,Arguments,Stream,First),
138 Count1 is Count - 1,
139 resp_parse_array(Stream,Count1,Rest),
140 !
Redis protocol parser and writer.
*/