Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Updated interface for error handlers

  • Loading branch information...
commit 77ea894e08b251e6c42d6ca68a24dc3b1b380430 1 parent 85da81f
Dmitry Vasiliev authored
View
2  TODO
@@ -1,6 +1,8 @@
General
-------
+- Fix recursion in encoder/decoder decorators
+
- More encodings
- Add error policies ("strict", "ignore"...)
View
64 src/encodings.erl
@@ -51,14 +51,14 @@
%% Error handler function:
%%
%% <pre>
-%% error_handler({encode, function()}, {error, Encoded, string()}) -> R
+%% error_handler(encode, {error, Encoded, string()}) -> R
%% Encoded = binary()
-%% R = binary() | {error, Encoded, string()}
-%% | {incomplete, Encoded, string()}
-%% error_handler({decode, function()}, {error, Decoded, binary()}) -> R
+%% R = {repeat, string()} | {continue, binary()}
+%% | {error, Encoded, string()}
+%% error_handler(decode, {error, Decoded, binary()}) -> R
%% Decoded = string()
-%% R = string() | {error, Decoded, binary()}
-%% | {incomplete, Decoded, binary()}
+%% R = {repeat, binary()} | {continue, string()}
+%% | {error, Decoded, binary()}
%% </pre>
%%
-module(encodings).
@@ -105,7 +105,7 @@ behaviour_info(_Other) ->
%% Encoded = binary()
%% Rest = string()
%%
-encode(Unicode, Encoding, ErrorHandler) ->
+encode(Unicode, Encoding, ErrorHandler) when is_list(Unicode) ->
case getencoder(Encoding, ErrorHandler) of
{ok, Encoder} ->
Encoder(Unicode);
@@ -128,7 +128,7 @@ encode(Unicode, Encoding) ->
%% Decoded = string()
%% Rest = binary()
%%
-decode(String, Encoding, ErrorHandler) ->
+decode(String, Encoding, ErrorHandler) when is_binary(String) ->
case getdecoder(Encoding, ErrorHandler) of
{ok, Decoder} ->
Decoder(String);
@@ -152,7 +152,7 @@ getencoder(Encoding, ErrorHandler) ->
{ok, Handler} ->
case gen_server:call(?MODULE, {getencoder, Encoding}) of
{ok, Encoder} ->
- {ok, decorate_encoder(Encoder, Handler)};
+ {ok, fun (U) -> encoder(U, Encoder, Handler) end};
Result ->
Result
end;
@@ -163,15 +163,19 @@ getencoder(Encoding, ErrorHandler) ->
getencoder(Encoding) ->
getencoder(Encoding, strict).
-decorate_encoder(Encoder, Handler) ->
- fun
- (Unicode) ->
- case Encoder(Unicode) of
- {error, _, _}=Error ->
- Handler({encode, Encoder}, Error);
- Result ->
- Result
- end
+encoder(Unicode, Encoder, Handler) when is_list(Unicode) ->
+ case Encoder(Unicode) of
+ {error, _, _}=Error ->
+ case Handler(encode, Error) of
+ {continue, S} ->
+ S;
+ {reply, U} ->
+ encoder(U, Encoder, Handler);
+ {error, _, _}=E ->
+ E
+ end;
+ Result ->
+ Result
end.
@@ -187,7 +191,7 @@ getdecoder(Encoding, ErrorHandler) ->
{ok, Handler} ->
case gen_server:call(?MODULE, {getdecoder, Encoding}) of
{ok, Decoder} ->
- {ok, decorate_decoder(Decoder, Handler)};
+ {ok, fun (S) -> decoder(S, Decoder, Handler) end};
Result ->
Result
end;
@@ -198,15 +202,19 @@ getdecoder(Encoding, ErrorHandler) ->
getdecoder(Encoding) ->
getdecoder(Encoding, strict).
-decorate_decoder(Decoder, Handler) ->
- fun
- (String) ->
- case Decoder(String) of
- {error, _, _}=Error ->
- Handler({decode, Decoder}, Error);
- Result ->
- Result
- end
+decoder(String, Decoder, Handler) when is_binary(String) ->
+ case Decoder(String) of
+ {error, _, _}=Error ->
+ case Handler(decode, Error) of
+ {continue, U} ->
+ U;
+ {reply, S} ->
+ decoder(S, Decoder, Handler);
+ {error, _, _}=E ->
+ E
+ end;
+ Result ->
+ Result
end.
View
30 src/encodings_errors.erl
@@ -32,12 +32,36 @@
-vsn("0.1").
%% Public interface
--export([get_builtin_errors/0, strict_handler/2]).
+-export([get_builtin_errors/0, strict_handler/2, ignore_handler/2]).
-get_builtin_errors() ->
- [{strict, fun encodings_errors:strict_handler/2}].
+%%
+%% @doc Return builtin error handlers
+%% @spec get_builtin_errors() -> [{atom(), function()}]
+%%
+get_builtin_errors() -> [
+ {strict, fun encodings_errors:strict_handler/2},
+ {ignore, fun encodings_errors:ignore_handler/2},
+ {skip, fun encodings_errors:skip_handler/2}
+ ].
+%%
+%% @doc Return encoding/decoding error as is
+%%
strict_handler(_, ErrorInfo) ->
ErrorInfo.
+
+
+%%
+%% @doc Ignore error and return encoded/decoded head
+%%
+ignore_handler(_, {error, Head, _}) ->
+ {continue, Head}.
+
+
+%%
+%% @doc Skip erroneous characters
+%%
+skip_handler(encode, {error, String, Rest}) ->
+ not_implemented.
View
20 src/encodings_tests.erl
@@ -129,6 +129,13 @@ test_registration_override() ->
ok.
+test_register_error_handler() ->
+ Handler = fun (_, Error) -> Error end,
+ true = encodings:register_error(myhandler, Handler),
+ {ok, Handler} = encodings:lookup_error(myhandler),
+ ok.
+
+
%%
%% Tests
%%
@@ -174,3 +181,16 @@ normalize_encoding_test_() -> [
?_assertEqual("encoding", encodings:normalize_encoding(" encoding -_")),
?_assertEqual("encoding_1", encodings:normalize_encoding("encoding - 1"))
].
+
+
+error_handler_test_() -> {setup, fun setup/0, fun cleanup/1, [
+ ?_assertEqual(ok, test_register_error_handler()),
+ ?_assertEqual([16#2014],
+ encodings:decode(<<16#97, 16#98, 16#99>>, "1251", ignore)),
+ ?_assertEqual(<<16#97>>,
+ encodings:encode([16#2014, 16#fffd, 16#2122], "1251", ignore))
+ %?_assertEqual([16#2014, 16#2122],
+ % encodings:decode(<<16#97, 16#98, 16#99>>, "1251", skip)),
+ %?_assertEqual(<<16#97, 16#99>>,
+ % encodings:encode([16#2014, 16#fffd, 16#2122], "1251", skip))
+ ]}.
Please sign in to comment.
Something went wrong with that request. Please try again.