summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorILYA Khlopotov <iilyak@apache.org>2018-11-22 20:25:58 +0000
committerILYA Khlopotov <iilyak@apache.org>2018-11-23 14:11:13 +0000
commit14f0e53795108b55a2621da419ce6802d346ee0d (patch)
tree20182ac1691543630e7054430560b8129416b9b0
parentbae96cd40be5d952b2a35a39caa3f308bbe9d0b5 (diff)
downloadcouchdb-14f0e53795108b55a2621da419ce6802d346ee0d.tar.gz
Replace erl_parse based parser with our own
-rw-r--r--src/couch/src/couch_flags_config.erl50
1 files changed, 42 insertions, 8 deletions
diff --git a/src/couch/src/couch_flags_config.erl b/src/couch/src/couch_flags_config.erl
index 2d4532a88..513a8154f 100644
--- a/src/couch/src/couch_flags_config.erl
+++ b/src/couch/src/couch_flags_config.erl
@@ -21,6 +21,7 @@
]).
-define(DATA_INTERVAL, 1000).
+-define(MAX_FLAG_NAME_LENGTH, 256).
-type pattern()
:: binary(). %% non empty binary which optionally can end with *
@@ -120,14 +121,32 @@ parse_flags(_Tokens, _) ->
[flag_id()] | {error, Reason :: term()}.
parse_flags_term(FlagsBin) ->
- case couch_util:parse_term(<<"[", FlagsBin/binary, "]">>) of
- {ok, Flags} ->
- lists:usort(Flags);
- Term ->
- {error, {
- "Flags should be list of atoms (got \"~s\"): ~p",
- [FlagsBin, Term]
- }}
+ {Flags, Errors} = lists:splitwith(fun erlang:is_atom/1,
+ [parse_flag(F) || F <- split_by_comma(FlagsBin)]),
+ case Errors of
+ [] ->
+ lists:usort(Flags);
+ _ ->
+ {error, {
+ "Cannot parse list of tags: ~n~p",
+ Errors
+ }}
+ end.
+
+split_by_comma(Binary) ->
+ case binary:split(Binary, <<",">>, [global]) of
+ [<<>>] -> [];
+ Tokens -> Tokens
+ end.
+
+parse_flag(FlagName) when size(FlagName) > ?MAX_FLAG_NAME_LENGTH ->
+ {too_long, FlagName};
+parse_flag(FlagName) ->
+ FlagNameS = string:strip(binary_to_list(FlagName)),
+ try
+ list_to_existing_atom(FlagNameS)
+ catch
+ _:_ -> {invalid_flag, FlagName}
end.
-spec parse_pattern(Pattern :: binary()) -> parse_pattern().
@@ -337,4 +356,19 @@ test_config() ->
{"flag_bar||shards/test/exact", "true"}
].
+parse_flags_term_test_() ->
+ LongBinary = binary:copy(<<"a">>, ?MAX_FLAG_NAME_LENGTH + 1),
+ ExpectedError = {error, {"Cannot parse list of tags: ~n~p",
+ [{too_long, LongBinary}]}},
+ ExpectedUnknownError = {error,{"Cannot parse list of tags: ~n~p",
+ [{invalid_flag,<<"dddddddd">>}]}},
+ [
+ {"empty binary", ?_assertEqual([], parse_flags_term(<<>>))},
+ {"single flag", ?_assertEqual([fff], parse_flags_term(<<"fff">>))},
+ {"sorted", ?_assertEqual([aaa,bbb,fff], parse_flags_term(<<"fff,aaa,bbb">>))},
+ {"whitespace", ?_assertEqual([aaa,bbb,fff], parse_flags_term(<<"fff , aaa, bbb ">>))},
+ {"error", ?_assertEqual(ExpectedError, parse_flags_term(LongBinary))},
+ {"unknown_flag", ?_assertEqual(ExpectedUnknownError, parse_flags_term(<<"dddddddd">>))}
+ ].
+
-endif.