-module(liburi_parser). -export([ parse_scheme/1, parse_authority/1, parse_user_info/1, parse_host_port/1, parse_path/1, parse_query/1, parse_frag/1 ]). parse_scheme(Uri) -> parse_scheme(Uri, <<>>). parse_scheme(<<$:, Uri/binary>>, Acc) -> {Acc, Uri}; parse_scheme(<<>>, Acc) -> {<<>>, Acc}; parse_scheme(<>, Acc) -> parse_scheme(Rest, <>). parse_authority(<<$/, $/, Uri/binary>>) -> parse_authority(Uri, <<"">>); parse_authority(Uri) -> {<<>>, Uri}. parse_authority(<>, Acc) when C =:= $/; C =:= $? -> {Acc, <>}; parse_authority(<<>>, Acc) -> {Acc, <<>>}; parse_authority(<>, Acc) -> parse_authority(Rest, <>). parse_user_info(Authority) -> parse_user_info(Authority, <<>>). parse_user_info(<<$@, HostPort/binary>>, Acc) -> {Acc, HostPort}; parse_user_info(<<>>, Acc) -> {<<>>, Acc}; parse_user_info(<>, Acc) -> parse_user_info(HostPort, <>). parse_host_port(HostPort) -> case binary:split(HostPort, <<":">>) of [Host] -> {Host, undefined}; [Host, <<>>] -> {Host, undefined}; [Host, Port] -> {Host, list_to_integer(binary_to_list(Port))}; _ -> throw({uri_error, {invalid_host_port, HostPort}}) end. parse_path(Uri) -> case parse_path(Uri, []) of {<<>>, Rest} -> {<<"/">>, Rest}; Result -> Result end. parse_path(<>, Acc) when C =:= $?; C =:= $# -> {list_to_binary(lists:reverse(Acc)), <>}; parse_path(<>, Acc) -> parse_path(Rest, [C | Acc]); parse_path(<<>>, Acc) -> {list_to_binary(lists:reverse(Acc)), <<"">>}. parse_query(<<$?, Uri/binary>>) -> parse_query(Uri, <<>>); parse_query(Uri) -> {<<>>, Uri}. parse_query(<<$#, Uri/binary>>, Acc) -> {Acc, <<$#, Uri/binary>>}; parse_query(<<>>, Acc) -> {Acc, <<"">>}; parse_query(<>, Acc) -> parse_query(Rest, <>). parse_frag(<<$#, Frag/binary>>) -> liburi_utils:unquote(Frag); parse_frag(<<>>) -> <<>>; parse_frag(Data) -> throw({uri_error, {data_left_after_parsing, Data}}).