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 !.
44resp_write(_,[]) :- !. 45resp_write(Stream,[First|Rest]) :- 46 resp_write_one(Stream,First), 47 resp_write(Stream,Rest). 48 49resp_write_one(Stream,string(String)) :- 50 format(Stream,"+~w~w",[String,"\r\n"]). 51resp_write_one(Stream,error(String)) :- 52 format(Stream,"-~w~w",[String,"\r\n"]). 53resp_write_one(Stream,integer(String)) :- 54 format(Stream,":~w~w",[String,"\r\n"]). 55resp_write_one(Stream,bulk(nil)) :- 56 format(Stream,"$~w~w",["-1","\r\n"]). 57resp_write_one(Stream,bulk(String)) :- 58 unicode_byte_length(String,Length), 59 format(Stream,"$~w~w~w~w",[Length,"\r\n",String,"\r\n"]). 60resp_write_one(Stream,array(nil)) :- 61 format(Stream,"*-1~w",["\r\n"]), 62 !. 63resp_write_one(Stream,array(Array)) :- 64 resp_write_one_array(Array,ResultArray), 65 length(Array,Length), 66 format(Stream,"*~w~w~w",[Length,"\r\n",ResultArray]). 67 68resp_write_one_array([],"") :- !. 69resp_write_one_array([First|Rest],ResultString) :- 70 new_memory_file(MF), 71 open_memory_file(MF, write, Stream), 72 resp_write_one(Stream,First), 73 close(Stream), 74 memory_file_to_string(MF,FirstResult,utf8), 75 free_memory_file(MF), 76 resp_write_one_array(Rest,ResultRest), 77 string_concat(FirstResult,ResultRest,ResultString).
83resp_parse(Stream,[Result|RestResult]) :- 84 read_line_to_codes(Stream,[TypeCode|ArgumentCodes]), 85 char_code(Type,TypeCode), 86 atom_chars(Arguments,ArgumentCodes), 87 resp_parse(Type,Arguments,Stream,Result), 88 resp_parse(Stream,RestResult). 89resp_parse(_,[]) :- !. 90 91resp_parse('+',Argument,_,string(Argument)) :- !. 92resp_parse(':',Argument,_,integer(ArgumentInteger)) :- 93 atom_number(Argument,ArgumentInteger), 94 !. 95resp_parse('-',Argument,_,error(Argument)) :- !. 96resp_parse('$',Argument,_,bulk(nil)) :- 97 atom_number(Argument,Count), 98 Count < 0, 99 !. 100resp_parse('$',Argument,Stream,bulk(Result)) :- 101 atom_number(Argument,Count), 102 get_chars(Stream,ResultChars,Count), 103 string_codes(Result,ResultChars), 104 seek(Stream,2,current,_), 105 !. 106resp_parse('*',Argument,Stream,array(Result)) :- 107 atom_number(Argument,Count), 108 resp_parse_array(Stream,Count,Result), 109 !. 110 111resp_parse_array(_,-1,nil) :- !. 112resp_parse_array(_,0,[]) :- !. 113resp_parse_array(Stream,Count,[First|Rest]) :- 114 read_line_to_codes(Stream,[TypeCode|ArgumentCodes]), 115 char_code(Type,TypeCode), 116 atom_chars(Arguments,ArgumentCodes), 117 resp_parse(Type,Arguments,Stream,First), 118 Count1 is Count - 1, 119 resp_parse_array(Stream,Count1,Rest), 120 !
Redis protocol parser and writer.
*/