Browse Source

Simplify the cow_http_hd code

Also rename the macros for inline lowercasing to ?LOWER,
and move the type detection macros to cow_parse.hrl.
Loïc Hoguin 10 years ago
parent
commit
8bd6a5fc57
5 changed files with 360 additions and 695 deletions
  1. 29 147
      include/cow_inline.hrl
  2. 79 0
      include/cow_parse.hrl
  3. 1 1
      src/cow_http.erl
  4. 244 540
      src/cow_http_hd.erl
  5. 7 7
      src/cow_multipart.erl

+ 29 - 147
include/cow_inline.hrl

@@ -15,95 +15,6 @@
 -ifndef(COW_INLINE_HRL).
 -define(COW_INLINE_HRL, 1).
 
-%% IS_ALPHA(Character)
-
--define(IS_ALPHA(C),
-	C =:= $a orelse C =:= $b orelse C =:= $c orelse C =:= $d orelse C =:= $e orelse
-	C =:= $f orelse C =:= $g orelse C =:= $h orelse C =:= $i orelse C =:= $j orelse
-	C =:= $k orelse C =:= $l orelse C =:= $m orelse C =:= $n orelse C =:= $o orelse
-	C =:= $p orelse C =:= $q orelse C =:= $r orelse C =:= $s orelse C =:= $t orelse
-	C =:= $u orelse C =:= $v orelse C =:= $w orelse C =:= $x orelse C =:= $y orelse
-	C =:= $z orelse
-	C =:= $A orelse C =:= $B orelse C =:= $C orelse C =:= $D orelse C =:= $E orelse
-	C =:= $F orelse C =:= $G orelse C =:= $H orelse C =:= $I orelse C =:= $J orelse
-	C =:= $K orelse C =:= $L orelse C =:= $M orelse C =:= $N orelse C =:= $O orelse
-	C =:= $P orelse C =:= $Q orelse C =:= $R orelse C =:= $S orelse C =:= $T orelse
-	C =:= $U orelse C =:= $V orelse C =:= $W orelse C =:= $X orelse C =:= $Y orelse
-	C =:= $Z
-).
-
-%% IS_ALPHANUM(Character)
-
--define(IS_ALPHANUM(C), ?IS_ALPHA(C) orelse ?IS_DIGIT(C)).
-
-%% IS_CHAR(Character)
-
--define(IS_CHAR(C), C > 0, C < 128).
-
-%% IS_DIGIT(Character)
-
--define(IS_DIGIT(C),
-	C =:= $0 orelse C =:= $1 orelse C =:= $2 orelse C =:= $3 orelse C =:= $4 orelse
-	C =:= $5 orelse C =:= $6 orelse C =:= $7 orelse C =:= $8 orelse C =:= $9
-).
-
-%% IS_ETAGC(Character)
-
--define(IS_ETAGC(C), C =:= 16#21; C >= 16#23, C =/= 16#7f).
-
-%% IS_HEX(Character)
-
--define(IS_HEX(C),
-	?IS_DIGIT(C) orelse
-	C =:= $a orelse C =:= $b orelse C =:= $c orelse
-	C =:= $d orelse C =:= $e orelse C =:= $f orelse
-	C =:= $A orelse C =:= $B orelse C =:= $C orelse
-	C =:= $D orelse C =:= $E orelse C =:= $F).
-
-%% IS_LHEX(Character)
-
--define(IS_LHEX(C),
-	?IS_DIGIT(C) orelse
-	C =:= $a orelse C =:= $b orelse C =:= $c orelse
-	C =:= $d orelse C =:= $e orelse C =:= $f).
-
-%% IS_TOKEN(Character)
-
--define(IS_TOKEN(C),
-	?IS_ALPHA(C) orelse ?IS_DIGIT(C)
-	orelse C =:= $! orelse C =:= $# orelse C =:= $$ orelse C =:= $% orelse C =:= $&
-	orelse C =:= $' orelse C =:= $* orelse C =:= $+ orelse C =:= $- orelse C =:= $.
-	orelse C =:= $^ orelse C =:= $_ orelse C =:= $` orelse C =:= $| orelse C =:= $~
-).
-
-%% IS_TOKEN68(Character)
-
--define(IS_TOKEN68(C),
-	?IS_ALPHA(C) orelse ?IS_DIGIT(C) orelse
-		C =:= $- orelse C =:= $. orelse C =:= $_ orelse
-		C =:= $~ orelse C =:= $+ orelse C =:= $/).
-
-%% IS_URI_UNRESERVED(Character)
-
--define(IS_URI_UNRESERVED(C),
-	?IS_ALPHA(C) orelse ?IS_DIGIT(C) orelse
-	C =:= $- orelse C =:= $. orelse C =:= $_ orelse C =:= $~).
-
-%% IS_URI_SUB_DELIMS(Character)
-
--define(IS_URI_SUB_DELIMS(C),
-	C =:= $! orelse C =:= $$ orelse C =:= $& orelse C =:= $' orelse
-	C =:= $( orelse C =:= $) orelse C =:= $* orelse C =:= $+ orelse
-	C =:= $, orelse C =:= $; orelse C =:= $=).
-
-%% IS_VCHAR(Character)
-
--define(IS_VCHAR(C), C =:= $\t; C > 31, C < 127).
-
-%% IS_VCHAR_OBS(Character)
-
--define(IS_VCHAR_OBS(C), C =:= $\t; C > 31, C =/= 127).
-
 %% LC(Character)
 
 -define(LC(C), case C of
@@ -136,12 +47,18 @@
 	_ -> C
 end).
 
-%% INLINE_LOWERCASE(Function, Rest, Acc, ...)
+%% LOWER(Bin)
+%%
+%% Lowercase the entire binary string in a binary comprehension.
+
+-define(LOWER(Bin), << << ?LC(C) >> || << C >> <= Bin >>).
+
+%% LOWERCASE(Function, Rest, Acc, ...)
 %%
 %% To be included at the end of a case block.
 %% Defined for up to 10 extra arguments.
 
--define(INLINE_LOWERCASE(Function, Rest, Acc),
+-define(LOWER(Function, Rest, Acc), case C of
 	$A -> Function(Rest, << Acc/binary, $a >>);
 	$B -> Function(Rest, << Acc/binary, $b >>);
 	$C -> Function(Rest, << Acc/binary, $c >>);
@@ -169,9 +86,9 @@ end).
 	$Y -> Function(Rest, << Acc/binary, $y >>);
 	$Z -> Function(Rest, << Acc/binary, $z >>);
 	C -> Function(Rest, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, Acc),
+-define(LOWER(Function, Rest, A0, Acc), case C of
 	$A -> Function(Rest, A0, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, << Acc/binary, $c >>);
@@ -199,9 +116,9 @@ end).
 	$Y -> Function(Rest, A0, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, Acc),
+-define(LOWER(Function, Rest, A0, A1, Acc), case C of
 	$A -> Function(Rest, A0, A1, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, << Acc/binary, $c >>);
@@ -229,9 +146,9 @@ end).
 	$Y -> Function(Rest, A0, A1, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, << Acc/binary, $c >>);
@@ -259,9 +176,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $c >>);
@@ -289,9 +206,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $c >>);
@@ -319,9 +236,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, A5, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $c >>);
@@ -349,9 +266,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, A5, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, A5, A6, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $c >>);
@@ -379,9 +296,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $c >>);
@@ -409,9 +326,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $c >>);
@@ -439,9 +356,9 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, << Acc/binary, C >>)
-).
+end).
 
--define(INLINE_LOWERCASE(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc),
+-define(LOWER(Function, Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc), case C of
 	$A -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $a >>);
 	$B -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $b >>);
 	$C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $c >>);
@@ -469,41 +386,6 @@ end).
 	$Y -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $y >>);
 	$Z -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, $z >>);
 	C -> Function(Rest, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, << Acc/binary, C >>)
-).
-
-%% INLINE_LOWERCASE_BC(Bin)
-%%
-%% Lowercase the entire binary string in a binary comprehension.
-
--define(INLINE_LOWERCASE_BC(Bin),
-	<< << case C of
-		$A -> $a;
-		$B -> $b;
-		$C -> $c;
-		$D -> $d;
-		$E -> $e;
-		$F -> $f;
-		$G -> $g;
-		$H -> $h;
-		$I -> $i;
-		$J -> $j;
-		$K -> $k;
-		$L -> $l;
-		$M -> $m;
-		$N -> $n;
-		$O -> $o;
-		$P -> $p;
-		$Q -> $q;
-		$R -> $r;
-		$S -> $s;
-		$T -> $t;
-		$U -> $u;
-		$V -> $v;
-		$W -> $w;
-		$X -> $x;
-		$Y -> $y;
-		$Z -> $z;
-		C -> C
-	end >> || << C >> <= Bin >>).
+end).
 
 -endif.

+ 79 - 0
include/cow_parse.hrl

@@ -0,0 +1,79 @@
+%% Copyright (c) 2015, Loïc Hoguin <essen@ninenines.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-ifndef(COW_PARSE_HRL).
+-define(COW_PARSE_HRL, 1).
+
+-define(IS_ALPHA(C),
+	C =:= $a orelse C =:= $b orelse C =:= $c orelse C =:= $d orelse C =:= $e orelse
+	C =:= $f orelse C =:= $g orelse C =:= $h orelse C =:= $i orelse C =:= $j orelse
+	C =:= $k orelse C =:= $l orelse C =:= $m orelse C =:= $n orelse C =:= $o orelse
+	C =:= $p orelse C =:= $q orelse C =:= $r orelse C =:= $s orelse C =:= $t orelse
+	C =:= $u orelse C =:= $v orelse C =:= $w orelse C =:= $x orelse C =:= $y orelse
+	C =:= $z orelse
+	C =:= $A orelse C =:= $B orelse C =:= $C orelse C =:= $D orelse C =:= $E orelse
+	C =:= $F orelse C =:= $G orelse C =:= $H orelse C =:= $I orelse C =:= $J orelse
+	C =:= $K orelse C =:= $L orelse C =:= $M orelse C =:= $N orelse C =:= $O orelse
+	C =:= $P orelse C =:= $Q orelse C =:= $R orelse C =:= $S orelse C =:= $T orelse
+	C =:= $U orelse C =:= $V orelse C =:= $W orelse C =:= $X orelse C =:= $Y orelse
+	C =:= $Z
+).
+
+-define(IS_ALPHANUM(C), ?IS_ALPHA(C) orelse ?IS_DIGIT(C)).
+-define(IS_CHAR(C), C > 0, C < 128).
+
+-define(IS_DIGIT(C),
+	C =:= $0 orelse C =:= $1 orelse C =:= $2 orelse C =:= $3 orelse C =:= $4 orelse
+	C =:= $5 orelse C =:= $6 orelse C =:= $7 orelse C =:= $8 orelse C =:= $9).
+
+-define(IS_ETAGC(C), C =:= 16#21; C >= 16#23, C =/= 16#7f).
+
+-define(IS_HEX(C),
+	?IS_DIGIT(C) orelse
+	C =:= $a orelse C =:= $b orelse C =:= $c orelse
+	C =:= $d orelse C =:= $e orelse C =:= $f orelse
+	C =:= $A orelse C =:= $B orelse C =:= $C orelse
+	C =:= $D orelse C =:= $E orelse C =:= $F).
+
+-define(IS_LHEX(C),
+	?IS_DIGIT(C) orelse
+	C =:= $a orelse C =:= $b orelse C =:= $c orelse
+	C =:= $d orelse C =:= $e orelse C =:= $f).
+
+-define(IS_TOKEN(C),
+	?IS_ALPHA(C) orelse ?IS_DIGIT(C)
+	orelse C =:= $! orelse C =:= $# orelse C =:= $$ orelse C =:= $% orelse C =:= $&
+	orelse C =:= $' orelse C =:= $* orelse C =:= $+ orelse C =:= $- orelse C =:= $.
+	orelse C =:= $^ orelse C =:= $_ orelse C =:= $` orelse C =:= $| orelse C =:= $~).
+
+-define(IS_TOKEN68(C),
+	?IS_ALPHA(C) orelse ?IS_DIGIT(C) orelse
+		C =:= $- orelse C =:= $. orelse C =:= $_ orelse
+		C =:= $~ orelse C =:= $+ orelse C =:= $/).
+
+-define(IS_URI_UNRESERVED(C),
+	?IS_ALPHA(C) orelse ?IS_DIGIT(C) orelse
+	C =:= $- orelse C =:= $. orelse C =:= $_ orelse C =:= $~).
+
+-define(IS_URI_SUB_DELIMS(C),
+	C =:= $! orelse C =:= $$ orelse C =:= $& orelse C =:= $' orelse
+	C =:= $( orelse C =:= $) orelse C =:= $* orelse C =:= $+ orelse
+	C =:= $, orelse C =:= $; orelse C =:= $=).
+
+-define(IS_VCHAR(C), C =:= $\t; C > 31, C < 127).
+-define(IS_VCHAR_OBS(C), C =:= $\t; C > 31, C =/= 127).
+-define(IS_WS(C), C =:= $\s orelse C =:= $\t).
+-define(IS_WS_COMMA(C), ?IS_WS(C) orelse C =:= $,).
+
+-endif.

+ 1 - 1
src/cow_http.erl

@@ -122,7 +122,7 @@ parse_hd_name(<< C, Rest/bits >>, Acc, SoFar) ->
 		$: -> parse_hd_before_value(Rest, Acc, SoFar);
 		$\s -> parse_hd_name_ws(Rest, Acc, SoFar);
 		$\t -> parse_hd_name_ws(Rest, Acc, SoFar);
-		?INLINE_LOWERCASE(parse_hd_name, Rest, Acc, SoFar)
+		_ -> ?LOWER(parse_hd_name, Rest, Acc, SoFar)
 	end.
 
 parse_hd_name_ws(<< C, Rest/bits >>, Acc, Name) ->

+ 244 - 540
src/cow_http_hd.erl

@@ -123,6 +123,7 @@
 -export_type([websocket_version/0]).
 
 -include("cow_inline.hrl").
+-include("cow_parse.hrl").
 
 -ifdef(TEST).
 -include_lib("triq/include/triq.hrl").
@@ -210,130 +211,78 @@ parse_accept(<<"*/*">>) ->
 parse_accept(Accept) ->
 	media_range_list(Accept, []).
 
-media_range_list(<<>>, Acc) -> lists:reverse(Acc);
-media_range_list(<< $\s, R/bits >>, Acc) -> media_range_list(R, Acc);
-media_range_list(<< $\t, R/bits >>, Acc) -> media_range_list(R, Acc);
-media_range_list(<< $,, R/bits >>, Acc) -> media_range_list(R, Acc);
-media_range_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_range_type, R, Acc, <<>>)
-	end.
+media_range_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) -> ?LOWER(media_range_type, R, Acc, <<>>);
+media_range_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> media_range_list(R, Acc);
+media_range_list(<<>>, Acc) -> lists:reverse(Acc).
 
-media_range_type(<< $/, R/bits >>, Acc, T) -> media_range_subtype(R, Acc, T, <<>>);
+media_range_type(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> ?LOWER(media_range_type, R, Acc, T);
+media_range_type(<< $/, C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> ?LOWER(media_range_subtype, R, Acc, T, <<>>);
 %% Special clause for badly behaving user agents that send * instead of */*.
-media_range_type(<< $;, R/bits >>, Acc, <<"*">>) -> media_range_before_param(R, Acc, <<"*">>, <<"*">>, []);
-media_range_type(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_range_type, R, Acc, T)
-	end.
+media_range_type(<< $;, R/bits >>, Acc, <<"*">>) -> media_range_before_param(R, Acc, <<"*">>, <<"*">>, []).
 
-media_range_subtype(<<>>, Acc, T, S) when S =/= <<>> -> lists:reverse([{{T, S, []}, 1000, []}|Acc]);
-media_range_subtype(<< $,, R/bits >>, Acc, T, S) when S =/= <<>> -> media_range_list(R, [{{T, S, []}, 1000, []}|Acc]);
-media_range_subtype(<< $;, R/bits >>, Acc, T, S) when S =/= <<>> -> media_range_before_param(R, Acc, T, S, []);
-media_range_subtype(<< $\s, R/bits >>, Acc, T, S) when S =/= <<>> -> media_range_before_semicolon(R, Acc, T, S, []);
-media_range_subtype(<< $\t, R/bits >>, Acc, T, S) when S =/= <<>> -> media_range_before_semicolon(R, Acc, T, S, []);
-media_range_subtype(<< C, R/bits >>, Acc, T, S) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_range_subtype, R, Acc, T, S)
-	end.
+media_range_subtype(<< C, R/bits >>, Acc, T, S) when ?IS_TOKEN(C) -> ?LOWER(media_range_subtype, R, Acc, T, S);
+media_range_subtype(R, Acc, T, S) -> media_range_param_sep(R, Acc, T, S, []).
 
-media_range_before_semicolon(<<>>, Acc, T, S, P) -> lists:reverse([{{T, S, lists:reverse(P)}, 1000, []}|Acc]);
-media_range_before_semicolon(<< $,, R/bits >>, Acc, T, S, P) -> media_range_list(R, [{{T, S, lists:reverse(P)}, 1000, []}|Acc]);
-media_range_before_semicolon(<< $;, R/bits >>, Acc, T, S, P) -> media_range_before_param(R, Acc, T, S, P);
-media_range_before_semicolon(<< $\s, R/bits >>, Acc, T, S, P) -> media_range_before_semicolon(R, Acc, T, S, P);
-media_range_before_semicolon(<< $\t, R/bits >>, Acc, T, S, P) -> media_range_before_semicolon(R, Acc, T, S, P).
+media_range_param_sep(<<>>, Acc, T, S, P) -> lists:reverse([{{T, S, lists:reverse(P)}, 1000, []}|Acc]);
+media_range_param_sep(<< $,, R/bits >>, Acc, T, S, P) -> media_range_list(R, [{{T, S, lists:reverse(P)}, 1000, []}|Acc]);
+media_range_param_sep(<< $;, R/bits >>, Acc, T, S, P) -> media_range_before_param(R, Acc, T, S, P);
+media_range_param_sep(<< C, R/bits >>, Acc, T, S, P) when ?IS_WS(C) -> media_range_param_sep(R, Acc, T, S, P).
 
-media_range_before_param(<< $\s, R/bits >>, Acc, T, S, P) -> media_range_before_param(R, Acc, T, S, P);
-media_range_before_param(<< $\t, R/bits >>, Acc, T, S, P) -> media_range_before_param(R, Acc, T, S, P);
-%% Special clause for badly behaving user agents that send .123 instead of 0.123.
-media_range_before_param(<< $q, $=, $., R/bits >>, Acc, T, S, P) -> media_range_broken_weight(R, Acc, T, S, P);
+media_range_before_param(<< C, R/bits >>, Acc, T, S, P) when ?IS_WS(C) -> media_range_before_param(R, Acc, T, S, P);
 media_range_before_param(<< $q, $=, R/bits >>, Acc, T, S, P) -> media_range_weight(R, Acc, T, S, P);
-media_range_before_param(<< C, R/bits >>, Acc, T, S, P) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_range_param, R, Acc, T, S, P, <<>>)
-	end.
+media_range_before_param(<< C, R/bits >>, Acc, T, S, P) when ?IS_TOKEN(C) -> ?LOWER(media_range_param, R, Acc, T, S, P, <<>>).
 
 media_range_param(<< $=, $", R/bits >>, Acc, T, S, P, K) -> media_range_quoted(R, Acc, T, S, P, K, <<>>);
 media_range_param(<< $=, C, R/bits >>, Acc, T, S, P, K) when ?IS_TOKEN(C) -> media_range_value(R, Acc, T, S, P, K, << C >>);
-media_range_param(<< C, R/bits >>, Acc, T, S, P, K) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_range_param, R, Acc, T, S, P, K)
-	end.
+media_range_param(<< C, R/bits >>, Acc, T, S, P, K) when ?IS_TOKEN(C) -> ?LOWER(media_range_param, R, Acc, T, S, P, K).
 
-media_range_quoted(<< $", R/bits >>, Acc, T, S, P, K, V) -> media_range_before_semicolon(R, Acc, T, S, [{K, V}|P]);
+media_range_quoted(<< $", R/bits >>, Acc, T, S, P, K, V) -> media_range_param_sep(R, Acc, T, S, [{K, V}|P]);
 media_range_quoted(<< $\\, C, R/bits >>, Acc, T, S, P, K, V) when ?IS_VCHAR_OBS(C) -> media_range_quoted(R, Acc, T, S, P, K, << V/binary, C >>);
 media_range_quoted(<< C, R/bits >>, Acc, T, S, P, K, V) when ?IS_VCHAR_OBS(C) -> media_range_quoted(R, Acc, T, S, P, K, << V/binary, C >>).
 
-media_range_value(<<>>, Acc, T, S, P, K, V) -> lists:reverse([{{T, S, lists:reverse([{K, V}|P])}, 1000, []}|Acc]);
-media_range_value(<< $,, R/bits >>, Acc, T, S, P, K, V) -> media_range_list(R, [{{T, S, lists:reverse([{K, V}|P])}, 1000, []}|Acc]);
-media_range_value(<< $;, R/bits >>, Acc, T, S, P, K, V) -> media_range_before_param(R, Acc, T, S, [{K, V}|P]);
-media_range_value(<< $\s, R/bits >>, Acc, T, S, P, K, V) -> media_range_before_semicolon(R, Acc, T, S, [{K, V}|P]);
-media_range_value(<< $\t, R/bits >>, Acc, T, S, P, K, V) -> media_range_before_semicolon(R, Acc, T, S, [{K, V}|P]);
-media_range_value(<< C, R/bits >>, Acc, T, S, P, K, V) when ?IS_TOKEN(C) -> media_range_value(R, Acc, T, S, P, K, << V/binary, C >>).
-
-%% Special function for badly behaving user agents that send .123 instead of 0.123.
-media_range_broken_weight(<< A, B, C, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9, B >= $0, B =< $9, C >= $0, C =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10 + (C - $0), []);
-media_range_broken_weight(<< A, B, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9, B >= $0, B =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10, []);
-media_range_broken_weight(<< A, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100, []).
-
-media_range_weight(<< "1.000", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 1000, []);
-media_range_weight(<< "1.00", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 1000, []);
-media_range_weight(<< "1.0", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 1000, []);
-media_range_weight(<< "1.", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 1000, []);
-media_range_weight(<< "1", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 1000, []);
-media_range_weight(<< "0.", A, B, C, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9, B >= $0, B =< $9, C >= $0, C =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10 + (C - $0), []);
-media_range_weight(<< "0.", A, B, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9, B >= $0, B =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10, []);
-media_range_weight(<< "0.", A, R/bits >>, Acc, T, S, P)
-	when A >= $0, A =< $9 ->
-		accept_before_semicolon(R, Acc, T, S, P, (A - $0) * 100, []);
-media_range_weight(<< "0.", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 0, []);
-media_range_weight(<< "0", R/bits >>, Acc, T, S, P) -> accept_before_semicolon(R, Acc, T, S, P, 0, []).
-
-accept_before_semicolon(<<>>, Acc, T, S, P, Q, E) -> lists:reverse([{{T, S, lists:reverse(P)}, Q, lists:reverse(E)}|Acc]);
-accept_before_semicolon(<< $,, R/bits >>, Acc, T, S, P, Q, E) -> media_range_list(R, [{{T, S, lists:reverse(P)}, Q, lists:reverse(E)}|Acc]);
-accept_before_semicolon(<< $;, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_ext(R, Acc, T, S, P, Q, E);
-accept_before_semicolon(<< $\s, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_semicolon(R, Acc, T, S, P, Q, E);
-accept_before_semicolon(<< $\t, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_semicolon(R, Acc, T, S, P, Q, E).
-
-accept_before_ext(<< $\s, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_ext(R, Acc, T, S, P, Q, E);
-accept_before_ext(<< $\t, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_ext(R, Acc, T, S, P, Q, E);
-accept_before_ext(<< C, R/bits >>, Acc, T, S, P, Q, E) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(accept_ext, R, Acc, T, S, P, Q, E, <<>>)
-	end.
+media_range_value(<< C, R/bits >>, Acc, T, S, P, K, V) when ?IS_TOKEN(C) -> media_range_value(R, Acc, T, S, P, K, << V/binary, C >>);
+media_range_value(R, Acc, T, S, P, K, V) -> media_range_param_sep(R, Acc, T, S, [{K, V}|P]).
+
+media_range_weight(<< "1.000", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 1000, []);
+media_range_weight(<< "1.00", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 1000, []);
+media_range_weight(<< "1.0", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 1000, []);
+media_range_weight(<< "1.", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 1000, []);
+media_range_weight(<< "1", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 1000, []);
+media_range_weight(<< "0.", A, B, C, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A), ?IS_DIGIT(B), ?IS_DIGIT(C) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10 + (C - $0), []);
+media_range_weight(<< "0.", A, B, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A), ?IS_DIGIT(B) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10, []);
+media_range_weight(<< "0.", A, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100, []);
+media_range_weight(<< "0.", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 0, []);
+media_range_weight(<< "0", R/bits >>, Acc, T, S, P) -> accept_ext_sep(R, Acc, T, S, P, 0, []);
+%% Special clauses for badly behaving user agents that send .123 instead of 0.123.
+media_range_weight(<< ".", A, B, C, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A), ?IS_DIGIT(B), ?IS_DIGIT(C) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10 + (C - $0), []);
+media_range_weight(<< ".", A, B, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A), ?IS_DIGIT(B) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100 + (B - $0) * 10, []);
+media_range_weight(<< ".", A, R/bits >>, Acc, T, S, P) when ?IS_DIGIT(A) ->
+	accept_ext_sep(R, Acc, T, S, P, (A - $0) * 100, []).
+
+accept_ext_sep(<<>>, Acc, T, S, P, Q, E) -> lists:reverse([{{T, S, lists:reverse(P)}, Q, lists:reverse(E)}|Acc]);
+accept_ext_sep(<< $,, R/bits >>, Acc, T, S, P, Q, E) -> media_range_list(R, [{{T, S, lists:reverse(P)}, Q, lists:reverse(E)}|Acc]);
+accept_ext_sep(<< $;, R/bits >>, Acc, T, S, P, Q, E) -> accept_before_ext(R, Acc, T, S, P, Q, E);
+accept_ext_sep(<< C, R/bits >>, Acc, T, S, P, Q, E) when ?IS_WS(C) -> accept_ext_sep(R, Acc, T, S, P, Q, E).
+
+accept_before_ext(<< C, R/bits >>, Acc, T, S, P, Q, E) when ?IS_WS(C) -> accept_before_ext(R, Acc, T, S, P, Q, E);
+accept_before_ext(<< C, R/bits >>, Acc, T, S, P, Q, E) when ?IS_TOKEN(C) -> ?LOWER(accept_ext, R, Acc, T, S, P, Q, E, <<>>).
 
-accept_ext(<<>>, Acc, T, S, P, Q, E, K) -> lists:reverse([{{T, S, lists:reverse(P)}, Q, lists:reverse([K|E])}|Acc]);
-accept_ext(<< $,, R/bits >>, Acc, T, S, P, Q, E, K) -> media_range_list(R, [{{T, S, lists:reverse(P)}, Q, lists:reverse([K|E])}|Acc]);
-accept_ext(<< $;, R/bits >>, Acc, T, S, P, Q, E, K) -> accept_before_ext(R, Acc, T, S, P, Q, [K|E]);
-accept_ext(<< $\s, R/bits >>, Acc, T, S, P, Q, E, K) -> accept_before_semicolon(R, Acc, T, S, P, Q, [K|E]);
-accept_ext(<< $\t, R/bits >>, Acc, T, S, P, Q, E, K) -> accept_before_semicolon(R, Acc, T, S, P, Q, [K|E]);
 accept_ext(<< $=, $", R/bits >>, Acc, T, S, P, Q, E, K) -> accept_quoted(R, Acc, T, S, P, Q, E, K, <<>>);
 accept_ext(<< $=, C, R/bits >>, Acc, T, S, P, Q, E, K) when ?IS_TOKEN(C) -> accept_value(R, Acc, T, S, P, Q, E, K, << C >>);
-accept_ext(<< C, R/bits >>, Acc, T, S, P, Q, E, K) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(accept_ext, R, Acc, T, S, P, Q, E, K)
-	end.
+accept_ext(<< C, R/bits >>, Acc, T, S, P, Q, E, K) when ?IS_TOKEN(C) -> ?LOWER(accept_ext, R, Acc, T, S, P, Q, E, K);
+accept_ext(R, Acc, T, S, P, Q, E, K) -> accept_ext_sep(R, Acc, T, S, P, Q, [K|E]).
 
-accept_quoted(<< $", R/bits >>, Acc, T, S, P, Q, E, K, V) -> accept_before_semicolon(R, Acc, T, S, P, Q, [{K, V}|E]);
+accept_quoted(<< $", R/bits >>, Acc, T, S, P, Q, E, K, V) -> accept_ext_sep(R, Acc, T, S, P, Q, [{K, V}|E]);
 accept_quoted(<< $\\, C, R/bits >>, Acc, T, S, P, Q, E, K, V) when ?IS_VCHAR_OBS(C) -> accept_quoted(R, Acc, T, S, P, Q, E, K, << V/binary, C >>);
 accept_quoted(<< C, R/bits >>, Acc, T, S, P, Q, E, K, V) when ?IS_VCHAR_OBS(C) -> accept_quoted(R, Acc, T, S, P, Q, E, K, << V/binary, C >>).
 
-accept_value(<<>>, Acc, T, S, P, Q, E, K, V) -> lists:reverse([{{T, S, lists:reverse(P)}, Q, lists:reverse([{K, V}|E])}|Acc]);
-accept_value(<< $,, R/bits >>, Acc, T, S, P, Q, E, K, V) -> media_range_list(R, [{{T, S, lists:reverse(P)}, Q, lists:reverse([{K, V}|E])}|Acc]);
-accept_value(<< $;, R/bits >>, Acc, T, S, P, Q, E, K, V) -> accept_before_ext(R, Acc, T, S, P, Q, [{K, V}|E]);
-accept_value(<< $\s, R/bits >>, Acc, T, S, P, Q, E, K, V) -> accept_before_semicolon(R, Acc, T, S, P, Q, [{K, V}|E]);
-accept_value(<< $\t, R/bits >>, Acc, T, S, P, Q, E, K, V) -> accept_before_semicolon(R, Acc, T, S, P, Q, [{K, V}|E]);
-accept_value(<< C, R/bits >>, Acc, T, S, P, Q, E, K, V) when ?IS_TOKEN(C) -> accept_value(R, Acc, T, S, P, Q, E, K, << V/binary, C >>).
+accept_value(<< C, R/bits >>, Acc, T, S, P, Q, E, K, V) when ?IS_TOKEN(C) -> accept_value(R, Acc, T, S, P, Q, E, K, << V/binary, C >>);
+accept_value(R, Acc, T, S, P, Q, E, K, V) -> accept_ext_sep(R, Acc, T, S, P, Q, [{K, V}|E]).
 
 -ifdef(TEST).
 accept_ext() ->
@@ -368,13 +317,13 @@ prop_parse_accept() ->
 			<< _, Accept/binary >> = iolist_to_binary([[$,, A] || {_, _, _, _, _, A} <- L]),
 			ResL = parse_accept(Accept),
 			CheckedL = [begin
-				ExpectedP = [{?INLINE_LOWERCASE_BC(K), unquote(V)} || {K, V, _, _} <- P],
+				ExpectedP = [{?LOWER(K), unquote(V)} || {K, V, _, _} <- P],
 				ExpectedE = [case Ext of
-					{K, V, _, _} -> {?INLINE_LOWERCASE_BC(K), unquote(V)};
-					K -> ?INLINE_LOWERCASE_BC(K)
+					{K, V, _, _} -> {?LOWER(K), unquote(V)};
+					K -> ?LOWER(K)
 				end || Ext <- E],
-				ResT =:= ?INLINE_LOWERCASE_BC(T)
-					andalso ResS =:= ?INLINE_LOWERCASE_BC(S)
+				ResT =:= ?LOWER(T)
+					andalso ResS =:= ?LOWER(S)
 					andalso ResP =:= ExpectedP
 					andalso (ResW =:= W orelse (W =:= undefined andalso ResW =:= 1000))
 					andalso ((W =:= undefined andalso ResE =:= []) orelse (W =/= undefined andalso ResE =:= ExpectedE))
@@ -454,59 +403,38 @@ parse_accept_charset(Charset) ->
 	nonempty(conneg_list(Charset, [])).
 
 conneg_list(<<>>, Acc) -> lists:reverse(Acc);
-conneg_list(<< $\s, R/bits >>, Acc) -> conneg_list(R, Acc);
-conneg_list(<< $\t, R/bits >>, Acc) -> conneg_list(R, Acc);
-conneg_list(<< $\,, R/bits >>, Acc) -> conneg_list(R, Acc);
-conneg_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(conneg, R, Acc, <<>>)
-	end.
+conneg_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> conneg_list(R, Acc);
+conneg_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) -> ?LOWER(conneg, R, Acc, <<>>).
 
-conneg(<<>>, Acc, T) -> lists:reverse([{T, 1000}|Acc]);
-conneg(<< $,, R/bits >>, Acc, T) -> conneg_list(R, [{T, 1000}|Acc]);
-conneg(<< $;, R/bits >>, Acc, T) -> conneg_before_weight(R, Acc, T);
-conneg(<< $\s, R/bits >>, Acc, T) -> conneg_before_semicolon(R, Acc, T);
-conneg(<< $\t, R/bits >>, Acc, T) -> conneg_before_semicolon(R, Acc, T);
-conneg(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(conneg, R, Acc, T)
-	end.
+conneg(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> ?LOWER(conneg, R, Acc, T);
+conneg(R, Acc, T) -> conneg_param_sep(R, Acc, T).
 
-conneg_before_semicolon(<<>>, Acc, T) -> lists:reverse([{T, 1000}|Acc]);
-conneg_before_semicolon(<< $,, R/bits >>, Acc, T) -> conneg_list(R, [{T, 1000}|Acc]);
-conneg_before_semicolon(<< $;, R/bits >>, Acc, T) -> conneg_before_weight(R, Acc, T);
-conneg_before_semicolon(<< $\s, R/bits >>, Acc, T) -> conneg_before_semicolon(R, Acc, T);
-conneg_before_semicolon(<< $\t, R/bits >>, Acc, T) -> conneg_before_semicolon(R, Acc, T).
+conneg_param_sep(<<>>, Acc, T) -> lists:reverse([{T, 1000}|Acc]);
+conneg_param_sep(<< $,, R/bits >>, Acc, T) -> conneg_list(R, [{T, 1000}|Acc]);
+conneg_param_sep(<< $;, R/bits >>, Acc, T) -> conneg_before_weight(R, Acc, T);
+conneg_param_sep(<< C, R/bits >>, Acc, T) when ?IS_WS(C) -> conneg_param_sep(R, Acc, T).
 
-conneg_before_weight(<< $\s, R/bits >>, Acc, T) -> conneg_before_weight(R, Acc, T);
-conneg_before_weight(<< $\t, R/bits >>, Acc, T) -> conneg_before_weight(R, Acc, T);
+conneg_before_weight(<< C, R/bits >>, Acc, T) when ?IS_WS(C) -> conneg_before_weight(R, Acc, T);
 conneg_before_weight(<< $q, $=, R/bits >>, Acc, T) -> conneg_weight(R, Acc, T);
 %% Special clause for broken user agents that confuse ; and , separators.
-conneg_before_weight(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(conneg, R, [{T, 1000}|Acc], <<>>)
-	end.
+conneg_before_weight(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> ?LOWER(conneg, R, [{T, 1000}|Acc], <<>>).
 
 conneg_weight(<< "1.000", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 1000}|Acc]);
 conneg_weight(<< "1.00", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 1000}|Acc]);
 conneg_weight(<< "1.0", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 1000}|Acc]);
 conneg_weight(<< "1.", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 1000}|Acc]);
 conneg_weight(<< "1", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 1000}|Acc]);
-conneg_weight(<< "0.", A, B, C, R/bits >>, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9, C >= $0, C =< $9 ->
-		conneg_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
-conneg_weight(<< "0.", A, B, R/bits >>, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9 ->
-		conneg_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
-conneg_weight(<< "0.", A, R/bits >>, Acc, T)
-	when A >= $0, A =< $9 ->
-		conneg_list_sep(R, [{T, (A - $0) * 100}|Acc]);
+conneg_weight(<< "0.", A, B, C, R/bits >>, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B), ?IS_DIGIT(C) ->
+	conneg_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
+conneg_weight(<< "0.", A, B, R/bits >>, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B) ->
+	conneg_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
+conneg_weight(<< "0.", A, R/bits >>, Acc, T) when ?IS_DIGIT(A) ->
+	conneg_list_sep(R, [{T, (A - $0) * 100}|Acc]);
 conneg_weight(<< "0.", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 0}|Acc]);
 conneg_weight(<< "0", R/bits >>, Acc, T) -> conneg_list_sep(R, [{T, 0}|Acc]).
 
 conneg_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-conneg_list_sep(<< $\s, R/bits >>, Acc) -> conneg_list_sep(R, Acc);
-conneg_list_sep(<< $\t, R/bits >>, Acc) -> conneg_list_sep(R, Acc);
+conneg_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> conneg_list_sep(R, Acc);
 conneg_list_sep(<< $,, R/bits >>, Acc) -> conneg_list(R, Acc).
 
 -ifdef(TEST).
@@ -526,7 +454,7 @@ prop_parse_accept_charset() ->
 			<< _, AcceptCharset/binary >> = iolist_to_binary([[$,, A] || {_, _, A} <- L]),
 			ResL = parse_accept_charset(AcceptCharset),
 			CheckedL = [begin
-				ResC =:= ?INLINE_LOWERCASE_BC(Ch)
+				ResC =:= ?LOWER(Ch)
 					andalso (ResW =:= W orelse (W =:= undefined andalso ResW =:= 1000))
 			end || {{Ch, W, _}, {ResC, ResW}} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
@@ -577,6 +505,7 @@ accept_encoding() ->
 		end])}
 	).
 
+%% @todo This property seems useless, see prop_accept_charset.
 prop_parse_accept_encoding() ->
 	?FORALL(L,
 		non_empty(list(accept_encoding())),
@@ -584,7 +513,7 @@ prop_parse_accept_encoding() ->
 			<< _, AcceptEncoding/binary >> = iolist_to_binary([[$,, A] || {_, _, A} <- L]),
 			ResL = parse_accept_encoding(AcceptEncoding),
 			CheckedL = [begin
-				ResE =:= ?INLINE_LOWERCASE_BC(E)
+				ResE =:= ?LOWER(E)
 					andalso (ResW =:= W orelse (W =:= undefined andalso ResW =:= 1000))
 			end || {{E, W, _}, {ResE, ResW}} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
@@ -625,74 +554,49 @@ parse_accept_language(LanguageRange) ->
 	nonempty(language_range_list(LanguageRange, [])).
 
 language_range_list(<<>>, Acc) -> lists:reverse(Acc);
-language_range_list(<< $\s, R/bits >>, Acc) -> language_range_list(R, Acc);
-language_range_list(<< $\t, R/bits >>, Acc) -> language_range_list(R, Acc);
-language_range_list(<< $\,, R/bits >>, Acc) -> language_range_list(R, Acc);
-language_range_list(<< $*, R/bits >>, Acc) -> language_range_before_semicolon(R, Acc, <<"*">>);
+language_range_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> language_range_list(R, Acc);
+language_range_list(<< $*, R/bits >>, Acc) -> language_range_param_sep(R, Acc, <<"*">>);
 language_range_list(<< C, R/bits >>, Acc) when ?IS_ALPHA(C) ->
-	case C of
-		?INLINE_LOWERCASE(language_range, R, Acc, 1, <<>>)
-	end.
+	?LOWER(language_range, R, Acc, 1, <<>>).
 
-language_range(<<>>, Acc, _, T) -> lists:reverse([{T, 1000}|Acc]);
-language_range(<< $,, R/bits >>, Acc, _, T) -> language_range_list(R, [{T, 1000}|Acc]);
-language_range(<< $;, R/bits >>, Acc, _, T) -> language_range_before_weight(R, Acc, T);
-language_range(<< $\s, R/bits >>, Acc, _, T) -> language_range_before_semicolon(R, Acc, T);
-language_range(<< $\t, R/bits >>, Acc, _, T) -> language_range_before_semicolon(R, Acc, T);
-language_range(<< $-, R/bits >>, Acc, _, T) -> language_range_sub(R, Acc, 0, << T/binary, $- >>);
-language_range(<< _, _/bits >>, _, 8, _) -> error(badarg);
-language_range(<< C, R/bits >>, Acc, N, T) when ?IS_ALPHA(C) ->
-	case C of
-		?INLINE_LOWERCASE(language_range, R, Acc, N + 1, T)
-	end.
+language_range(<< $-, C, R/bits >>, Acc, _, T) when ?IS_ALPHANUM(C) ->
+	?LOWER(language_range_sub, R, Acc, 1, << T/binary, $- >>);
+language_range(<< C, R/bits >>, Acc, N, T) when ?IS_ALPHA(C), N < 8 ->
+	?LOWER(language_range, R, Acc, N + 1, T);
+language_range(R, Acc, _, T) -> language_range_param_sep(R, Acc, T).
 
-language_range_sub(<<>>, Acc, N, T) when N > 0 -> lists:reverse([{T, 1000}|Acc]);
-language_range_sub(<< $,, R/bits >>, Acc, N, T) when N > 0 -> language_range_list(R, [{T, 1000}|Acc]);
-language_range_sub(<< $;, R/bits >>, Acc, N, T) when N > 0 -> language_range_before_weight(R, Acc, T);
-language_range_sub(<< $\s, R/bits >>, Acc, N, T) when N > 0 -> language_range_before_semicolon(R, Acc, T);
-language_range_sub(<< $\t, R/bits >>, Acc, N, T) when N > 0 -> language_range_before_semicolon(R, Acc, T);
-language_range_sub(<< $-, R/bits >>, Acc, N, T) when N > 0 -> language_range_sub(R, Acc, 0, << T/binary, $- >>);
-language_range_sub(<< _, _/bits >>, _, 8, _) -> error(badarg);
-language_range_sub(<< C, R/bits >>, Acc, N, T) when ?IS_ALPHA(C); ?IS_DIGIT(C) ->
-	case C of
-		?INLINE_LOWERCASE(language_range_sub, R, Acc, N + 1, T)
-	end.
+language_range_sub(<< $-, R/bits >>, Acc, _, T) -> language_range_sub(R, Acc, 0, << T/binary, $- >>);
+language_range_sub(<< C, R/bits >>, Acc, N, T) when ?IS_ALPHANUM(C), N < 8 ->
+	?LOWER(language_range_sub, R, Acc, N + 1, T);
+language_range_sub(R, Acc, _, T) -> language_range_param_sep(R, Acc, T).
 
-language_range_before_semicolon(<<>>, Acc, T) -> lists:reverse([{T, 1000}|Acc]);
-language_range_before_semicolon(<< $,, R/bits >>, Acc, T) -> language_range_list(R, [{T, 1000}|Acc]);
-language_range_before_semicolon(<< $;, R/bits >>, Acc, T) -> language_range_before_weight(R, Acc, T);
-language_range_before_semicolon(<< $\s, R/bits >>, Acc, T) -> language_range_before_semicolon(R, Acc, T);
-language_range_before_semicolon(<< $\t, R/bits >>, Acc, T) -> language_range_before_semicolon(R, Acc, T).
+language_range_param_sep(<<>>, Acc, T) -> lists:reverse([{T, 1000}|Acc]);
+language_range_param_sep(<< $,, R/bits >>, Acc, T) -> language_range_list(R, [{T, 1000}|Acc]);
+language_range_param_sep(<< $;, R/bits >>, Acc, T) -> language_range_before_weight(R, Acc, T);
+language_range_param_sep(<< C, R/bits >>, Acc, T) when ?IS_WS(C) -> language_range_param_sep(R, Acc, T).
 
-language_range_before_weight(<< $\s, R/bits >>, Acc, T) -> language_range_before_weight(R, Acc, T);
-language_range_before_weight(<< $\t, R/bits >>, Acc, T) -> language_range_before_weight(R, Acc, T);
+language_range_before_weight(<< C, R/bits >>, Acc, T) when ?IS_WS(C) -> language_range_before_weight(R, Acc, T);
 language_range_before_weight(<< $q, $=, R/bits >>, Acc, T) -> language_range_weight(R, Acc, T);
 %% Special clause for broken user agents that confuse ; and , separators.
 language_range_before_weight(<< C, R/bits >>, Acc, T) when ?IS_ALPHA(C) ->
-	case C of
-		?INLINE_LOWERCASE(language_range, R, [{T, 1000}|Acc], 1, <<>>)
-	end.
+	?LOWER(language_range, R, [{T, 1000}|Acc], 1, <<>>).
 
 language_range_weight(<< "1.000", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 1000}|Acc]);
 language_range_weight(<< "1.00", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 1000}|Acc]);
 language_range_weight(<< "1.0", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 1000}|Acc]);
 language_range_weight(<< "1.", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 1000}|Acc]);
 language_range_weight(<< "1", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 1000}|Acc]);
-language_range_weight(<< "0.", A, B, C, R/bits >>, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9, C >= $0, C =< $9 ->
-		language_range_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
-language_range_weight(<< "0.", A, B, R/bits >>, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9 ->
-		language_range_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
-language_range_weight(<< "0.", A, R/bits >>, Acc, T)
-	when A >= $0, A =< $9 ->
-		language_range_list_sep(R, [{T, (A - $0) * 100}|Acc]);
+language_range_weight(<< "0.", A, B, C, R/bits >>, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B), ?IS_DIGIT(C) ->
+	language_range_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
+language_range_weight(<< "0.", A, B, R/bits >>, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B) ->
+	language_range_list_sep(R, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
+language_range_weight(<< "0.", A, R/bits >>, Acc, T) when ?IS_DIGIT(A) ->
+	language_range_list_sep(R, [{T, (A - $0) * 100}|Acc]);
 language_range_weight(<< "0.", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 0}|Acc]);
 language_range_weight(<< "0", R/bits >>, Acc, T) -> language_range_list_sep(R, [{T, 0}|Acc]).
 
 language_range_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-language_range_list_sep(<< $\s, R/bits >>, Acc) -> language_range_list_sep(R, Acc);
-language_range_list_sep(<< $\t, R/bits >>, Acc) -> language_range_list_sep(R, Acc);
+language_range_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> language_range_list_sep(R, Acc);
 language_range_list_sep(<< $,, R/bits >>, Acc) -> language_range_list(R, Acc).
 
 -ifdef(TEST).
@@ -721,7 +625,7 @@ prop_parse_accept_language() ->
 			<< _, AcceptLanguage/binary >> = iolist_to_binary([[$,, A] || {_, _, A} <- L]),
 			ResL = parse_accept_language(AcceptLanguage),
 			CheckedL = [begin
-				ResR =:= ?INLINE_LOWERCASE_BC(R)
+				ResR =:= ?LOWER(R)
 					andalso (ResW =:= W orelse (W =:= undefined andalso ResW =:= 1000))
 			end || {{R, W, _}, {ResR, ResW}} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
@@ -900,39 +804,30 @@ validate_auth_bearer_eq(<< $=, R/bits >>) -> validate_auth_bearer_eq(R);
 validate_auth_bearer_eq(<<>>) -> ok.
 
 auth_digest_list(<<>>, Acc) -> lists:reverse(Acc);
-auth_digest_list(<< $\s, R/bits >>, Acc) -> auth_digest_list(R, Acc);
-auth_digest_list(<< $\t, R/bits >>, Acc) -> auth_digest_list(R, Acc);
-auth_digest_list(<< $,, R/bits >>, Acc) -> auth_digest_list(R, Acc);
+auth_digest_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> auth_digest_list(R, Acc);
 auth_digest_list(<< "algorithm=", C, R/bits >>, Acc) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, <<"algorithm">>, << C >>);
 auth_digest_list(<< "cnonce=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"cnonce">>, <<>>);
-auth_digest_list(<< "qop=", C, R/bits >>, Acc) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, <<"qop">>, << C >>);
 auth_digest_list(<< "nc=", A, B, C, D, E, F, G, H, R/bits >>, Acc)
 		when ?IS_LHEX(A), ?IS_LHEX(B), ?IS_LHEX(C), ?IS_LHEX(D),
 			?IS_LHEX(E), ?IS_LHEX(F), ?IS_LHEX(G), ?IS_LHEX(H) ->
 	auth_digest_list_sep(R, [{<<"nc">>, << A, B, C, D, E, F, G, H >>}|Acc]);
 auth_digest_list(<< "nonce=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"nonce">>, <<>>);
 auth_digest_list(<< "opaque=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"opaque">>, <<>>);
+auth_digest_list(<< "qop=", C, R/bits >>, Acc) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, <<"qop">>, << C >>);
 auth_digest_list(<< "realm=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"realm">>, <<>>);
 auth_digest_list(<< "response=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"response">>, <<>>);
 auth_digest_list(<< "uri=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"uri">>, <<>>);
 auth_digest_list(<< "username=\"", R/bits >>, Acc) -> auth_digest_quoted(R, Acc, <<"username">>, <<>>);
 auth_digest_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(auth_digest_param, R, Acc, <<>>)
-	end.
+	?LOWER(auth_digest_param, R, Acc, <<>>).
 
 auth_digest_param(<< $=, $", R/bits >>, Acc, K) -> auth_digest_quoted(R, Acc, K, <<>>);
 auth_digest_param(<< $=, C, R/bits >>, Acc, K) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, K, << C >>);
 auth_digest_param(<< C, R/bits >>, Acc, K) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(auth_digest_param, R, Acc, K)
-	end.
+	?LOWER(auth_digest_param, R, Acc, K).
 
-auth_digest_token(<<>>, Acc, K, V) -> lists:reverse([{K, V}|Acc]);
-auth_digest_token(<< $,, R/bits >>, Acc, K, V) -> auth_digest_list(R, [{K, V}|Acc]);
-auth_digest_token(<< $\s, R/bits >>, Acc, K, V) -> auth_digest_list_sep(R, [{K, V}|Acc]);
-auth_digest_token(<< $\t, R/bits >>, Acc, K, V) -> auth_digest_list_sep(R, [{K, V}|Acc]);
-auth_digest_token(<< C, R/bits >>, Acc, K, V) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, K, << V/binary, C >>).
+auth_digest_token(<< C, R/bits >>, Acc, K, V) when ?IS_TOKEN(C) -> auth_digest_token(R, Acc, K, << V/binary, C >>);
+auth_digest_token(R, Acc, K, V) -> auth_digest_list_sep(R, [{K, V}|Acc]).
 
 auth_digest_quoted(<< $", R/bits >>, Acc, K, V) -> auth_digest_list_sep(R, [{K, V}|Acc]);
 auth_digest_quoted(<< $\\, C, R/bits >>, Acc, K, V) when ?IS_VCHAR_OBS(C) -> auth_digest_quoted(R, Acc, K, << V/binary, C >>);
@@ -940,8 +835,7 @@ auth_digest_quoted(<< C, R/bits >>, Acc, K, V) when ?IS_VCHAR_OBS(C) -> auth_dig
 
 auth_digest_list_sep(<<>>, Acc) -> lists:reverse(Acc);
 auth_digest_list_sep(<< $,, R/bits >>, Acc) -> auth_digest_list(R, Acc);
-auth_digest_list_sep(<< $\s, R/bits >>, Acc) -> auth_digest_list_sep(R, Acc);
-auth_digest_list_sep(<< $\t, R/bits >>, Acc) -> auth_digest_list_sep(R, Acc).
+auth_digest_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> auth_digest_list_sep(R, Acc).
 
 -ifdef(TEST).
 parse_authorization_test_() ->
@@ -1011,65 +905,41 @@ parse_cache_control(CacheControl) ->
 	nonempty(cache_directive_list(CacheControl, [])).
 
 cache_directive_list(<<>>, Acc) -> lists:reverse(Acc);
-cache_directive_list(<< $\s, R/bits >>, Acc) -> cache_directive_list(R, Acc);
-cache_directive_list(<< $\t, R/bits >>, Acc) -> cache_directive_list(R, Acc);
-cache_directive_list(<< $,, R/bits >>, Acc) -> cache_directive_list(R, Acc);
+cache_directive_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C)-> cache_directive_list(R, Acc);
 cache_directive_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(cache_directive, R, Acc, <<>>)
-	end.
-
-cache_directive(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-cache_directive(<< $\s, R/bits >>, Acc, T) -> cache_directive_list_sep(R, [T|Acc]);
-cache_directive(<< $\t, R/bits >>, Acc, T) -> cache_directive_list_sep(R, [T|Acc]);
-cache_directive(<< $,, R/bits >>, Acc, T) -> cache_directive_list(R, [T|Acc]);
-cache_directive(<< $=, $", R/bits >>, Acc, T = <<"no-cache">>) -> cache_directive_fields_list(R, Acc, T, []);
-cache_directive(<< $=, $", R/bits >>, Acc, T = <<"private">>) -> cache_directive_fields_list(R, Acc, T, []);
+	?LOWER(cache_directive, R, Acc, <<>>).
+
+cache_directive(<< $=, $", R/bits >>, Acc, T)
+		when T =:= <<"no-cache">> orelse T =:= <<"private">> ->
+	cache_directive_fields_list(R, Acc, T, []);
+cache_directive(<< $=, C, R/bits >>, Acc, T)
+		when ?IS_DIGIT(C), T =:= <<"max-age">> orelse T =:= <<"max-stale">>
+			orelse T =:= <<"min-fresh">> orelse T =:= <<"s-maxage">> ->
+	cache_directive_delta(R, Acc, T, (C - $0));
 cache_directive(<< $=, $", R/bits >>, Acc, T) -> cache_directive_quoted_string(R, Acc, T, <<>>);
-cache_directive(<< $=, C, R/bits >>, Acc, T = <<"max-age">>) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, T, (C - $0));
-cache_directive(<< $=, C, R/bits >>, Acc, T = <<"max-stale">>) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, T, (C - $0));
-cache_directive(<< $=, C, R/bits >>, Acc, T = <<"min-fresh">>) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, T, (C - $0));
-cache_directive(<< $=, C, R/bits >>, Acc, T = <<"s-maxage">>) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, T, (C - $0));
 cache_directive(<< $=, C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> cache_directive_token(R, Acc, T, << C >>);
 cache_directive(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(cache_directive, R, Acc, T)
-	end.
+	?LOWER(cache_directive, R, Acc, T);
+cache_directive(R, Acc, T) -> cache_directive_list_sep(R, [T|Acc]).
 
-cache_directive_delta(<<>>, Acc, K, V) -> lists:reverse([{K, V}|Acc]);
-cache_directive_delta(<< $\s, R/bits >>, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]);
-cache_directive_delta(<< $\t, R/bits >>, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]);
-cache_directive_delta(<< $,, R/bits >>, Acc, K, V) -> cache_directive_list(R, [{K, V}|Acc]);
-cache_directive_delta(<< C, R/bits >>, Acc, K, V) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, K, V * 10 + (C - $0)).
+cache_directive_delta(<< C, R/bits >>, Acc, K, V) when ?IS_DIGIT(C) -> cache_directive_delta(R, Acc, K, V * 10 + (C - $0));
+cache_directive_delta(R, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]).
 
-cache_directive_fields_list(<< $\s, R/bits >>, Acc, K, L) -> cache_directive_fields_list(R, Acc, K, L);
-cache_directive_fields_list(<< $\t, R/bits >>, Acc, K, L) -> cache_directive_fields_list(R, Acc, K, L);
-cache_directive_fields_list(<< $,, R/bits >>, Acc, K, L) -> cache_directive_fields_list(R, Acc, K, L);
+cache_directive_fields_list(<< C, R/bits >>, Acc, K, L) when ?IS_WS_COMMA(C) -> cache_directive_fields_list(R, Acc, K, L);
 cache_directive_fields_list(<< $", R/bits >>, Acc, K, L) -> cache_directive_list_sep(R, [{K, lists:reverse(L)}|Acc]);
 cache_directive_fields_list(<< C, R/bits >>, Acc, K, L) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(cache_directive_field, R, Acc, K, L, <<>>)
-	end.
+	?LOWER(cache_directive_field, R, Acc, K, L, <<>>).
 
-cache_directive_field(<< $\s, R/bits >>, Acc, K, L, F) -> cache_directive_fields_list_sep(R, Acc, K, [F|L]);
-cache_directive_field(<< $\t, R/bits >>, Acc, K, L, F) -> cache_directive_fields_list_sep(R, Acc, K, [F|L]);
-cache_directive_field(<< $,, R/bits >>, Acc, K, L, F) -> cache_directive_fields_list(R, Acc, K, [F|L]);
-cache_directive_field(<< $", R/bits >>, Acc, K, L, F) -> cache_directive_list_sep(R, [{K, lists:reverse([F|L])}|Acc]);
 cache_directive_field(<< C, R/bits >>, Acc, K, L, F) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(cache_directive_field, R, Acc, K, L, F)
-	end.
+	?LOWER(cache_directive_field, R, Acc, K, L, F);
+cache_directive_field(R, Acc, K, L, F) -> cache_directive_fields_list_sep(R, Acc, K, [F|L]).
 
-cache_directive_fields_list_sep(<< $\s, R/bits >>, Acc, K, L) -> cache_directive_fields_list_sep(R, Acc, K, L);
-cache_directive_fields_list_sep(<< $\t, R/bits >>, Acc, K, L) -> cache_directive_fields_list_sep(R, Acc, K, L);
+cache_directive_fields_list_sep(<< C, R/bits >>, Acc, K, L) when ?IS_WS(C) -> cache_directive_fields_list_sep(R, Acc, K, L);
 cache_directive_fields_list_sep(<< $,, R/bits >>, Acc, K, L) -> cache_directive_fields_list(R, Acc, K, L);
 cache_directive_fields_list_sep(<< $", R/bits >>, Acc, K, L) -> cache_directive_list_sep(R, [{K, lists:reverse(L)}|Acc]).
 
-cache_directive_token(<<>>, Acc, K, V) -> lists:reverse([{K, V}|Acc]);
-cache_directive_token(<< $\s, R/bits >>, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]);
-cache_directive_token(<< $\t, R/bits >>, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]);
-cache_directive_token(<< $,, R/bits >>, Acc, K, V) -> cache_directive_list(R, [{K, V}|Acc]);
-cache_directive_token(<< C, R/bits >>, Acc, K, V) when ?IS_TOKEN(C) -> cache_directive_token(R, Acc, K, << V/binary, C >>).
+cache_directive_token(<< C, R/bits >>, Acc, K, V) when ?IS_TOKEN(C) -> cache_directive_token(R, Acc, K, << V/binary, C >>);
+cache_directive_token(R, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]).
 
 cache_directive_quoted_string(<< $", R/bits >>, Acc, K, V) -> cache_directive_list_sep(R, [{K, V}|Acc]);
 cache_directive_quoted_string(<< $\\, C, R/bits >>, Acc, K, V) when ?IS_VCHAR_OBS(C) ->
@@ -1078,8 +948,7 @@ cache_directive_quoted_string(<< C, R/bits >>, Acc, K, V) when ?IS_VCHAR_OBS(C)
 	cache_directive_quoted_string(R, Acc, K, << V/binary, C >>).
 
 cache_directive_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-cache_directive_list_sep(<< $\s, R/bits >>, Acc) -> cache_directive_list_sep(R, Acc);
-cache_directive_list_sep(<< $\t, R/bits >>, Acc) -> cache_directive_list_sep(R, Acc);
+cache_directive_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> cache_directive_list_sep(R, Acc);
 cache_directive_list_sep(<< $,, R/bits >>, Acc) -> cache_directive_list(R, Acc).
 
 -ifdef(TEST).
@@ -1119,9 +988,9 @@ prop_parse_cache_control() ->
 			ResL = parse_cache_control(CacheControl),
 			CheckedL = [begin
 				ExpectedCc = case Cc of
-					{fields, K, V} -> {?INLINE_LOWERCASE_BC(K), [?INLINE_LOWERCASE_BC(F) || F <- V]};
-					{K, V} -> {?INLINE_LOWERCASE_BC(K), unquote(V)};
-					K -> ?INLINE_LOWERCASE_BC(K)
+					{fields, K, V} -> {?LOWER(K), [?LOWER(F) || F <- V]};
+					{K, V} -> {?LOWER(K), unquote(V)};
+					K -> ?LOWER(K)
 				end,
 				ExpectedCc =:= ResCc
 			end || {Cc, ResCc} <- lists:zip(L, ResL)],
@@ -1191,7 +1060,7 @@ prop_parse_connection() ->
 		begin
 			<< _, Connection/binary >> = iolist_to_binary([[$,, C] || C <- L]),
 			ResL = parse_connection(Connection),
-			CheckedL = [?INLINE_LOWERCASE_BC(Co) =:= ResC || {Co, ResC} <- lists:zip(L, ResL)],
+			CheckedL = [?LOWER(Co) =:= ResC || {Co, ResC} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
 		end).
 
@@ -1264,19 +1133,13 @@ parse_content_language(ContentLanguage) ->
 	nonempty(langtag_list(ContentLanguage, [])).
 
 langtag_list(<<>>, Acc) -> lists:reverse(Acc);
-langtag_list(<< $\s, R/bits >>, Acc) -> langtag_list(R, Acc);
-langtag_list(<< $\t, R/bits >>, Acc) -> langtag_list(R, Acc);
-langtag_list(<< $,, R/bits >>, Acc) -> langtag_list(R, Acc);
+langtag_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> langtag_list(R, Acc);
 langtag_list(<< A, B, C, R/bits >>, Acc) when ?IS_ALPHA(A), ?IS_ALPHA(B), ?IS_ALPHA(C) ->
 	langtag_extlang(R, Acc, << ?LC(A), ?LC(B), ?LC(C) >>, 0);
 langtag_list(<< A, B, R/bits >>, Acc) when ?IS_ALPHA(A), ?IS_ALPHA(B) ->
 	langtag_extlang(R, Acc, << ?LC(A), ?LC(B) >>, 0);
 langtag_list(<< X, R/bits >>, Acc) when X =:= $x; X =:= $X -> langtag_privateuse_sub(R, Acc, << $x >>, 0).
 
-langtag_extlang(<<>>, Acc, T, _) -> lists:reverse([T|Acc]);
-langtag_extlang(<< $,, R/bits >>, Acc, T, _) -> langtag_list(R, [T|Acc]);
-langtag_extlang(<< $\s, R/bits >>, Acc, T, _) -> langtag_list_sep(R, [T|Acc]);
-langtag_extlang(<< $\t, R/bits >>, Acc, T, _) -> langtag_list_sep(R, [T|Acc]);
 langtag_extlang(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T, _)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1303,10 +1166,6 @@ langtag_extlang(<< $-, A, B, C, R/bits >>, Acc, T, N)
 	end;
 langtag_extlang(R, Acc, T, _) -> langtag_region(R, Acc, T).
 
-langtag_script(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-langtag_script(<< $,, R/bits >>, Acc, T) -> langtag_list(R, [T|Acc]);
-langtag_script(<< $\s, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
-langtag_script(<< $\t, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
 langtag_script(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1328,10 +1187,6 @@ langtag_script(<< $-, A, B, C, D, R/bits >>, Acc, T)
 langtag_script(R, Acc, T) ->
 	langtag_region(R, Acc, T).
 
-langtag_region(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-langtag_region(<< $,, R/bits >>, Acc, T) -> langtag_list(R, [T|Acc]);
-langtag_region(<< $\s, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
-langtag_region(<< $\t, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
 langtag_region(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1357,10 +1212,6 @@ langtag_region(<< $-, A, B, C, R/bits >>, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B
 langtag_region(R, Acc, T) ->
 	langtag_variant(R, Acc, T).
 
-langtag_variant(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-langtag_variant(<< $,, R/bits >>, Acc, T) -> langtag_list(R, [T|Acc]);
-langtag_variant(<< $\s, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
-langtag_variant(<< $\t, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
 langtag_variant(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1382,17 +1233,10 @@ langtag_variant(<< $-, A, B, C, D, R/bits >>, Acc, T)
 langtag_variant(R, Acc, T) ->
 	langtag_extension(R, Acc, T).
 
-langtag_extension(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-langtag_extension(<< $,, R/bits >>, Acc, T) -> langtag_list(R, [T|Acc]);
-langtag_extension(<< $\s, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
-langtag_extension(<< $\t, R/bits >>, Acc, T) -> langtag_list_sep(R, [T|Acc]);
 langtag_extension(<< $-, X, R/bits >>, Acc, T) when X =:= $x; X =:= $X -> langtag_privateuse_sub(R, Acc, << T/binary, $-, $x >>, 0);
-langtag_extension(<< $-, S, R/bits >>, Acc, T) when ?IS_ALPHANUM(S) -> langtag_extension_sub(R, Acc, << T/binary, $-, ?LC(S) >>, 0).
+langtag_extension(<< $-, S, R/bits >>, Acc, T) when ?IS_ALPHANUM(S) -> langtag_extension_sub(R, Acc, << T/binary, $-, ?LC(S) >>, 0);
+langtag_extension(R, Acc, T) -> langtag_list_sep(R, [T|Acc]).
 
-langtag_extension_sub(<<>>, Acc, T, N) when N > 0 -> lists:reverse([T|Acc]);
-langtag_extension_sub(<< $,, R/bits >>, Acc, T, N) when N > 0 -> langtag_list(R, [T|Acc]);
-langtag_extension_sub(<< $\s, R/bits >>, Acc, T, N) when N > 0 -> langtag_list_sep(R, [T|Acc]);
-langtag_extension_sub(<< $\t, R/bits >>, Acc, T, N) when N > 0 -> langtag_list_sep(R, [T|Acc]);
 langtag_extension_sub(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T, N)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1420,10 +1264,6 @@ langtag_extension_sub(<< $-, A, B, R/bits >>, Acc, T, N)
 langtag_extension_sub(R, Acc, T, N) when N > 0 ->
 	langtag_extension(R, Acc, T).
 
-langtag_privateuse_sub(<<>>, Acc, T, N) when N > 0 -> lists:reverse([T|Acc]);
-langtag_privateuse_sub(<< $,, R/bits >>, Acc, T, N) when N > 0 -> langtag_list(R, [T|Acc]);
-langtag_privateuse_sub(<< $\s, R/bits >>, Acc, T, N) when N > 0 -> langtag_list_sep(R, [T|Acc]);
-langtag_privateuse_sub(<< $\t, R/bits >>, Acc, T, N) when N > 0 -> langtag_list_sep(R, [T|Acc]);
 langtag_privateuse_sub(<< $-, A, B, C, D, E, F, G, H, R/bits >>, Acc, T, N)
 		when ?IS_ALPHANUM(A), ?IS_ALPHANUM(B), ?IS_ALPHANUM(C), ?IS_ALPHANUM(D),
 			?IS_ALPHANUM(E), ?IS_ALPHANUM(F), ?IS_ALPHANUM(G), ?IS_ALPHANUM(H) ->
@@ -1450,12 +1290,12 @@ langtag_privateuse_sub(<< $-, A, B, R/bits >>, Acc, T, N)
 	langtag_privateuse_sub(R, Acc, << T/binary, $-, ?LC(A), ?LC(B) >>, N + 1);
 langtag_privateuse_sub(<< $-, A, R/bits >>, Acc, T, N)
 		when ?IS_ALPHANUM(A) ->
-	langtag_privateuse_sub(R, Acc, << T/binary, $-, ?LC(A) >>, N + 1).
+	langtag_privateuse_sub(R, Acc, << T/binary, $-, ?LC(A) >>, N + 1);
+langtag_privateuse_sub(R, Acc, T, N) when N > 0 -> langtag_list_sep(R, [T|Acc]).
 
 langtag_list_sep(<<>>, Acc) -> lists:reverse(Acc);
 langtag_list_sep(<< $,, R/bits >>, Acc) -> langtag_list(R, Acc);
-langtag_list_sep(<< $\s, R/bits >>, Acc) -> langtag_list_sep(R, Acc);
-langtag_list_sep(<< $\t, R/bits >>, Acc) -> langtag_list_sep(R, Acc).
+langtag_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> langtag_list_sep(R, Acc).
 
 -ifdef(TEST).
 langtag_language() -> vector(2, 3, alpha()).
@@ -1500,7 +1340,7 @@ prop_parse_content_language() ->
 		content_language(),
 		begin
 			ResL = parse_content_language(ContentLanguage),
-			CheckedL = [?INLINE_LOWERCASE_BC(T) =:= ResT || {T, ResT} <- lists:zip(L, ResL)],
+			CheckedL = [?LOWER(T) =:= ResT || {T, ResT} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
 		end).
 
@@ -1631,9 +1471,7 @@ horse_parse_content_length_giga() ->
 parse_content_range(<<"bytes */", C, R/bits >>) when ?IS_DIGIT(C) -> unsatisfied_range(R, C - $0);
 parse_content_range(<<"bytes ", C, R/bits >>) when ?IS_DIGIT(C) -> byte_range_first(R, C - $0);
 parse_content_range(<< C, R/bits >>) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(other_content_range_unit, R, <<>>)
-	end.
+	?LOWER(other_content_range_unit, R, <<>>).
 
 byte_range_first(<< $-, C, R/bits >>, First) when ?IS_DIGIT(C) -> byte_range_last(R, First, C - $0);
 byte_range_first(<< C, R/bits >>, First) when ?IS_DIGIT(C) -> byte_range_first(R, First * 10 + C - $0).
@@ -1651,9 +1489,7 @@ unsatisfied_range(<< C, R/bits >>, Complete) when ?IS_DIGIT(C) -> unsatisfied_ra
 
 other_content_range_unit(<< $\s, R/bits >>, Unit) -> other_content_range_resp(R, Unit, <<>>);
 other_content_range_unit(<< C, R/bits >>, Unit) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(other_content_range_unit, R, Unit)
-	end.
+	?LOWER(other_content_range_unit, R, Unit).
 
 other_content_range_resp(<<>>, Unit, Resp) -> {Unit, Resp};
 other_content_range_resp(<< C, R/bits >>, Unit, Resp) when ?IS_CHAR(C) -> other_content_range_resp(R, Unit, << Resp/binary, C >>).
@@ -1672,7 +1508,7 @@ content_range() ->
 			{token(), ?LET(L, list(abnf_char()), list_to_binary(L))}
 		]),
 		{case ContentRange of
-			{Unit, Resp} when is_binary(Unit) -> {?INLINE_LOWERCASE_BC(Unit), Resp};
+			{Unit, Resp} when is_binary(Unit) -> {?LOWER(Unit), Resp};
 			_ -> ContentRange
 		end, case ContentRange of
 			{bytes, First, Last, '*'} ->
@@ -1733,78 +1569,49 @@ horse_parse_content_range_other() ->
 
 -spec parse_content_type(binary()) -> media_type().
 parse_content_type(<< C, R/bits >>) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_type, R, <<>>)
-	end.
+	?LOWER(media_type, R, <<>>).
 
 media_type(<< $/, C, R/bits >>, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_subtype, R, T, <<>>)
-	end;
+	?LOWER(media_subtype, R, T, <<>>);
 media_type(<< C, R/bits >>, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_type, R, T)
-	end.
+	?LOWER(media_type, R, T).
 
-media_subtype(<<>>, T, S) -> {T, S, []};
-media_subtype(<< $;, R/bits >>, T, S) -> media_before_param(R, T, S, []);
-media_subtype(<< $\s, R/bits >>, T, S) -> media_before_semicolon(R, T, S, []);
-media_subtype(<< $\t, R/bits >>, T, S) -> media_before_semicolon(R, T, S, []);
 media_subtype(<< C, R/bits >>, T, S) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_subtype, R, T, S)
-	end.
+	?LOWER(media_subtype, R, T, S);
+media_subtype(R, T, S) -> media_param_sep(R, T, S, []).
 
-media_before_semicolon(<<>>, T, S, P) -> {T, S, lists:reverse(P)};
-media_before_semicolon(<< $;, R/bits >>, T, S, P) -> media_before_param(R, T, S, P);
-media_before_semicolon(<< $\s, R/bits >>, T, S, P) -> media_before_semicolon(R, T, S, P);
-media_before_semicolon(<< $\t, R/bits >>, T, S, P) -> media_before_semicolon(R, T, S, P).
+media_param_sep(<<>>, T, S, P) -> {T, S, lists:reverse(P)};
+media_param_sep(<< $;, R/bits >>, T, S, P) -> media_before_param(R, T, S, P);
+media_param_sep(<< C, R/bits >>, T, S, P) when ?IS_WS(C) -> media_param_sep(R, T, S, P).
 
-media_before_param(<< $\s, R/bits >>, T, S, P) -> media_before_param(R, T, S, P);
-media_before_param(<< $\t, R/bits >>, T, S, P) -> media_before_param(R, T, S, P);
+media_before_param(<< C, R/bits >>, T, S, P) when ?IS_WS(C)-> media_before_param(R, T, S, P);
 media_before_param(<< "charset=", $", R/bits >>, T, S, P) -> media_charset_quoted(R, T, S, P, <<>>);
 media_before_param(<< "charset=", R/bits >>, T, S, P) -> media_charset(R, T, S, P, <<>>);
 media_before_param(<< C, R/bits >>, T, S, P) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_param, R, T, S, P, <<>>)
-	end.
+	?LOWER(media_param, R, T, S, P, <<>>).
 
 media_charset_quoted(<< $", R/bits >>, T, S, P, V) ->
-	media_before_semicolon(R, T, S, [{<<"charset">>, V}|P]);
+	media_param_sep(R, T, S, [{<<"charset">>, V}|P]);
 media_charset_quoted(<< $\\, C, R/bits >>, T, S, P, V) when ?IS_VCHAR_OBS(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_charset_quoted, R, T, S, P, V)
-	end;
+	?LOWER(media_charset_quoted, R, T, S, P, V);
 media_charset_quoted(<< C, R/bits >>, T, S, P, V) when ?IS_VCHAR_OBS(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_charset_quoted, R, T, S, P, V)
-	end.
+	?LOWER(media_charset_quoted, R, T, S, P, V).
 
-media_charset(<<>>, T, S, P, V) -> {T, S, lists:reverse([{<<"charset">>, V}|P])};
-media_charset(<< $;, R/bits >>, T, S, P, V) -> media_before_param(R, T, S, [{<<"charset">>, V}|P]);
-media_charset(<< $\s, R/bits >>, T, S, P, V) -> media_before_semicolon(R, T, S, [{<<"charset">>, V}|P]);
-media_charset(<< $\t, R/bits >>, T, S, P, V) -> media_before_semicolon(R, T, S, [{<<"charset">>, V}|P]);
 media_charset(<< C, R/bits >>, T, S, P, V) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_charset, R, T, S, P, V)
-	end.
+	?LOWER(media_charset, R, T, S, P, V);
+media_charset(R, T, S, P, V) -> media_param_sep(R, T, S, [{<<"charset">>, V}|P]).
 
 media_param(<< $=, $", R/bits >>, T, S, P, K) -> media_quoted(R, T, S, P, K, <<>>);
 media_param(<< $=, C, R/bits >>, T, S, P, K) when ?IS_TOKEN(C) -> media_value(R, T, S, P, K, << C >>);
 media_param(<< C, R/bits >>, T, S, P, K) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(media_param, R, T, S, P, K)
-	end.
+	?LOWER(media_param, R, T, S, P, K).
 
-media_quoted(<< $", R/bits >>, T, S, P, K, V) -> media_before_semicolon(R, T, S, [{K, V}|P]);
+media_quoted(<< $", R/bits >>, T, S, P, K, V) -> media_param_sep(R, T, S, [{K, V}|P]);
 media_quoted(<< $\\, C, R/bits >>, T, S, P, K, V) when ?IS_VCHAR_OBS(C) -> media_quoted(R, T, S, P, K, << V/binary, C >>);
 media_quoted(<< C, R/bits >>, T, S, P, K, V) when ?IS_VCHAR_OBS(C) -> media_quoted(R, T, S, P, K, << V/binary, C >>).
 
-media_value(<<>>, T, S, P, K, V) -> {T, S, lists:reverse([{K, V}|P])};
-media_value(<< $;, R/bits >>, T, S, P, K, V) -> media_before_param(R, T, S, [{K, V}|P]);
-media_value(<< $\s, R/bits >>, T, S, P, K, V) -> media_before_semicolon(R, T, S, [{K, V}|P]);
-media_value(<< $\t, R/bits >>, T, S, P, K, V) -> media_before_semicolon(R, T, S, [{K, V}|P]);
-media_value(<< C, R/bits >>, T, S, P, K, V) when ?IS_TOKEN(C) -> media_value(R, T, S, P, K, << V/binary, C >>).
+media_value(<< C, R/bits >>, T, S, P, K, V) when ?IS_TOKEN(C) -> media_value(R, T, S, P, K, << V/binary, C >>);
+media_value(R, T, S, P, K, V) -> media_param_sep(R, T, S, [{K, V}|P]).
 
 -ifdef(TEST).
 media_type_parameter() ->
@@ -1824,12 +1631,12 @@ prop_parse_content_type() ->
 		media_type(),
 		begin
 			{ResT, ResS, ResP} = parse_content_type(MediaType),
-			ExpectedP = [case ?INLINE_LOWERCASE_BC(K) of
-				<<"charset">> -> {<<"charset">>, ?INLINE_LOWERCASE_BC(unquote(V))};
+			ExpectedP = [case ?LOWER(K) of
+				<<"charset">> -> {<<"charset">>, ?LOWER(unquote(V))};
 				LowK -> {LowK, unquote(V)}
 			end || {K, V, _, _} <- P],
-			ResT =:= ?INLINE_LOWERCASE_BC(T)
-				andalso ResS =:= ?INLINE_LOWERCASE_BC(S)
+			ResT =:= ?LOWER(T)
+				andalso ResS =:= ?LOWER(S)
 				andalso ResP =:= ExpectedP
 		end
 	).
@@ -2051,16 +1858,12 @@ parse_host(Host) ->
 ipv6_address(<< $] >>, IP) -> {<< IP/binary, $] >>, undefined};
 ipv6_address(<< $], $:, Port/bits >>, IP) -> {<< IP/binary, $] >>, binary_to_integer(Port)};
 ipv6_address(<< C, R/bits >>, IP) when ?IS_HEX(C) orelse C =:= $: orelse C =:= $. ->
-	case C of
-		?INLINE_LOWERCASE(ipv6_address, R, IP)
-	end.
+	?LOWER(ipv6_address, R, IP).
 
 reg_name(<<>>, Name) -> {Name, undefined};
 reg_name(<< $:, Port/bits >>, Name) -> {Name, binary_to_integer(Port)};
 reg_name(<< C, R/bits >>, Name) when ?IS_URI_UNRESERVED(C) orelse ?IS_URI_SUB_DELIMS(C) ->
-	case C of
-		?INLINE_LOWERCASE(reg_name, R, Name)
-	end.
+	?LOWER(reg_name, R, Name).
 
 -ifdef(TEST).
 host_chars() -> "!$&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~".
@@ -2071,7 +1874,7 @@ host_port() ->
 		{host(), oneof([undefined, int(1, 65535)])},
 		begin
 			HostBin = list_to_binary(Host),
-			{{?INLINE_LOWERCASE_BC(HostBin), Port},
+			{{?LOWER(HostBin), Port},
 				case Port of
 					undefined -> HostBin;
 					_ -> << HostBin/binary, $:, (integer_to_binary(Port))/binary >>
@@ -2127,9 +1930,7 @@ parse_if_match(IfMatch) ->
 	nonempty(etag_list(IfMatch, [])).
 
 etag_list(<<>>, Acc) -> lists:reverse(Acc);
-etag_list(<< $\s, R/bits >>, Acc) -> etag_list(R, Acc);
-etag_list(<< $\t, R/bits >>, Acc) -> etag_list(R, Acc);
-etag_list(<< $,, R/bits >>, Acc) -> etag_list(R, Acc);
+etag_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> etag_list(R, Acc);
 etag_list(<< $W, $/, $", R/bits >>, Acc) -> etag(R, Acc, weak, <<>>);
 etag_list(<< $", R/bits >>, Acc) -> etag(R, Acc, strong, <<>>).
 
@@ -2137,8 +1938,7 @@ etag(<< $", R/bits >>, Acc, Strength, Tag) -> etag_list_sep(R, [{Strength, Tag}|
 etag(<< C, R/bits >>, Acc, Strength, Tag) when ?IS_ETAGC(C) -> etag(R, Acc, Strength, << Tag/binary, C >>).
 
 etag_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-etag_list_sep(<< $\s, R/bits >>, Acc) -> etag_list_sep(R, Acc);
-etag_list_sep(<< $\t, R/bits >>, Acc) -> etag_list_sep(R, Acc);
+etag_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> etag_list_sep(R, Acc);
 etag_list_sep(<< $,, R/bits >>, Acc) -> etag_list(R, Acc).
 
 -ifdef(TEST).
@@ -2366,14 +2166,10 @@ parse_proxy_authorization(ProxyAuthorization) ->
 parse_range(<<"bytes=", R/bits >>) ->
 	bytes_range_set(R, []);
 parse_range(<< C, R/bits >>) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(other_range_unit, R, <<>>)
-	end.
+	?LOWER(other_range_unit, R, <<>>).
 
 bytes_range_set(<<>>, Acc) -> {bytes, lists:reverse(Acc)};
-bytes_range_set(<< $\s, R/bits >>, Acc) -> bytes_range_set(R, Acc);
-bytes_range_set(<< $\t, R/bits >>, Acc) -> bytes_range_set(R, Acc);
-bytes_range_set(<< $,, R/bits >>, Acc) -> bytes_range_set(R, Acc);
+bytes_range_set(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> bytes_range_set(R, Acc);
 bytes_range_set(<< $-, C, R/bits >>, Acc) when ?IS_DIGIT(C) -> bytes_range_suffix_spec(R, Acc, C - $0);
 bytes_range_set(<< C, R/bits >>, Acc) when ?IS_DIGIT(C) -> bytes_range_spec(R, Acc, C - $0).
 
@@ -2388,16 +2184,13 @@ bytes_range_suffix_spec(<< C, R/bits >>, Acc, Suffix) when ?IS_DIGIT(C) -> bytes
 bytes_range_suffix_spec(R, Acc, Suffix) -> bytes_range_set_sep(R, [-Suffix|Acc]).
 
 bytes_range_set_sep(<<>>, Acc) -> {bytes, lists:reverse(Acc)};
-bytes_range_set_sep(<< $\s, R/bits >>, Acc) -> bytes_range_set_sep(R, Acc);
-bytes_range_set_sep(<< $\t, R/bits >>, Acc) -> bytes_range_set_sep(R, Acc);
+bytes_range_set_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> bytes_range_set_sep(R, Acc);
 bytes_range_set_sep(<< $,, R/bits >>, Acc) -> bytes_range_set(R, Acc).
 
 other_range_unit(<< $=, C, R/bits >>, U) when ?IS_VCHAR(C) ->
 	other_range_set(R, U, << C >>);
 other_range_unit(<< C, R/bits >>, U) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(other_range_unit, R, U)
-	end.
+	?LOWER(other_range_unit, R, U).
 
 other_range_set(<<>>, U, S) ->
 	{U, S};
@@ -2439,7 +2232,7 @@ prop_parse_range() ->
 		begin
 			Range2 = case Range of
 				{bytes, _} -> Range;
-				{Unit, Set} -> {?INLINE_LOWERCASE_BC(Unit), Set}
+				{Unit, Set} -> {?LOWER(Unit), Set}
 			end,
 			Range2 =:= parse_range(RangeBin)
 		end).
@@ -2545,47 +2338,31 @@ parse_sec_websocket_extensions(SecWebSocketExtensions) ->
 	nonempty(ws_extension_list(SecWebSocketExtensions, [])).
 
 ws_extension_list(<<>>, Acc) -> lists:reverse(Acc);
-ws_extension_list(<< $\s, R/bits >>, Acc) -> ws_extension_list(R, Acc);
-ws_extension_list(<< $\t, R/bits >>, Acc) -> ws_extension_list(R, Acc);
-ws_extension_list(<< $,, R/bits >>, Acc) -> ws_extension_list(R, Acc);
+ws_extension_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> ws_extension_list(R, Acc);
 ws_extension_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) -> ws_extension(R, Acc, << C >>).
 
-ws_extension(<<>>, Acc, E) -> lists:reverse([{E, []}|Acc]);
-ws_extension(<< $,, R/bits >>, Acc, E) -> ws_extension_list(R, [{E, []}|Acc]);
-ws_extension(<< $;, R/bits >>, Acc, E) -> ws_extension_before_param(R, Acc, E, []);
-ws_extension(<< $\s, R/bits >>, Acc, E) -> ws_extension_before_semicolon(R, Acc, E, []);
-ws_extension(<< $\t, R/bits >>, Acc, E) -> ws_extension_before_semicolon(R, Acc, E, []);
-ws_extension(<< C, R/bits >>, Acc, E) when ?IS_TOKEN(C) -> ws_extension(R, Acc, << E/binary, C >>).
-
-ws_extension_before_semicolon(<<>>, Acc, E, P) -> lists:reverse([{E, lists:reverse(P)}|Acc]);
-ws_extension_before_semicolon(<< $,, R/bits >>, Acc, E, P) -> ws_extension_list(R, [{E, lists:reverse(P)}|Acc]);
-ws_extension_before_semicolon(<< $;, R/bits >>, Acc, E, P) -> ws_extension_before_param(R, Acc, E, P);
-ws_extension_before_semicolon(<< $\s, R/bits >>, Acc, E, P) -> ws_extension_before_semicolon(R, Acc, E, P);
-ws_extension_before_semicolon(<< $\t, R/bits >>, Acc, E, P) -> ws_extension_before_semicolon(R, Acc, E, P).
-
-ws_extension_before_param(<< $\s, R/bits >>, Acc, E, P) -> ws_extension_before_param(R, Acc, E, P);
-ws_extension_before_param(<< $\t, R/bits >>, Acc, E, P) -> ws_extension_before_param(R, Acc, E, P);
+ws_extension(<< C, R/bits >>, Acc, E) when ?IS_TOKEN(C) -> ws_extension(R, Acc, << E/binary, C >>);
+ws_extension(R, Acc, E) -> ws_extension_param_sep(R, Acc, E, []).
+
+ws_extension_param_sep(<<>>, Acc, E, P) -> lists:reverse([{E, lists:reverse(P)}|Acc]);
+ws_extension_param_sep(<< $,, R/bits >>, Acc, E, P) -> ws_extension_list(R, [{E, lists:reverse(P)}|Acc]);
+ws_extension_param_sep(<< $;, R/bits >>, Acc, E, P) -> ws_extension_before_param(R, Acc, E, P);
+ws_extension_param_sep(<< C, R/bits >>, Acc, E, P) when ?IS_WS(C) -> ws_extension_param_sep(R, Acc, E, P).
+
+ws_extension_before_param(<< C, R/bits >>, Acc, E, P) when ?IS_WS(C) -> ws_extension_before_param(R, Acc, E, P);
 ws_extension_before_param(<< C, R/bits >>, Acc, E, P) when ?IS_TOKEN(C) -> ws_extension_param(R, Acc, E, P, << C >>).
 
-ws_extension_param(<<>>, Acc, E, P, K) -> lists:reverse([{E, lists:reverse([K|P])}|Acc]);
-ws_extension_param(<< $\s, R/bits >>, Acc, E, P, K) -> ws_extension_before_semicolon(R, Acc, E, [K|P]);
-ws_extension_param(<< $\t, R/bits >>, Acc, E, P, K) -> ws_extension_before_semicolon(R, Acc, E, [K|P]);
-ws_extension_param(<< $,, R/bits >>, Acc, E, P, K) -> ws_extension_list(R, [{E, lists:reverse([K|P])}|Acc]);
-ws_extension_param(<< $;, R/bits >>, Acc, E, P, K) -> ws_extension_before_param(R, Acc, E, [K|P]);
 ws_extension_param(<< $=, $", R/bits >>, Acc, E, P, K) -> ws_extension_quoted(R, Acc, E, P, K, <<>>);
 ws_extension_param(<< $=, C, R/bits >>, Acc, E, P, K) when ?IS_TOKEN(C) -> ws_extension_value(R, Acc, E, P, K, << C >>);
-ws_extension_param(<< C, R/bits >>, Acc, E, P, K) when ?IS_TOKEN(C) -> ws_extension_param(R, Acc, E, P, << K/binary, C >>).
+ws_extension_param(<< C, R/bits >>, Acc, E, P, K) when ?IS_TOKEN(C) -> ws_extension_param(R, Acc, E, P, << K/binary, C >>);
+ws_extension_param(R, Acc, E, P, K) -> ws_extension_param_sep(R, Acc, E, [K|P]).
 
-ws_extension_quoted(<< $", R/bits >>, Acc, E, P, K, V) -> ws_extension_before_semicolon(R, Acc, E, [{K, V}|P]);
+ws_extension_quoted(<< $", R/bits >>, Acc, E, P, K, V) -> ws_extension_param_sep(R, Acc, E, [{K, V}|P]);
 ws_extension_quoted(<< $\\, C, R/bits >>, Acc, E, P, K, V) when ?IS_TOKEN(C) -> ws_extension_quoted(R, Acc, E, P, K, << V/binary, C >>);
 ws_extension_quoted(<< C, R/bits >>, Acc, E, P, K, V) when ?IS_TOKEN(C) -> ws_extension_quoted(R, Acc, E, P, K, << V/binary, C >>).
 
-ws_extension_value(<<>>, Acc, E, P, K, V) -> lists:reverse([{E, lists:reverse([{K, V}|P])}|Acc]);
-ws_extension_value(<< $\s, R/bits >>, Acc, E, P, K, V) -> ws_extension_before_semicolon(R, Acc, E, [{K, V}|P]);
-ws_extension_value(<< $\t, R/bits >>, Acc, E, P, K, V) -> ws_extension_before_semicolon(R, Acc, E, [{K, V}|P]);
-ws_extension_value(<< $,, R/bits >>, Acc, E, P, K, V) -> ws_extension_list(R, [{E, lists:reverse([{K, V}|P])}|Acc]);
-ws_extension_value(<< $;, R/bits >>, Acc, E, P, K, V) -> ws_extension_before_param(R, Acc, E, [{K, V}|P]);
-ws_extension_value(<< C, R/bits >>, Acc, E, P, K, V) when ?IS_TOKEN(C) -> ws_extension_value(R, Acc, E, P, K, << V/binary, C >>).
+ws_extension_value(<< C, R/bits >>, Acc, E, P, K, V) when ?IS_TOKEN(C) -> ws_extension_value(R, Acc, E, P, K, << V/binary, C >>);
+ws_extension_value(R, Acc, E, P, K, V) -> ws_extension_param_sep(R, Acc, E, [{K, V}|P]).
 
 -ifdef(TEST).
 quoted_token() ->
@@ -2692,21 +2469,17 @@ horse_parse_sec_websocket_protocol_req() ->
 
 -spec parse_sec_websocket_protocol_resp(binary()) -> binary().
 parse_sec_websocket_protocol_resp(<< C, R/bits >>) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(token_ci, R, <<>>)
-	end.
+	?LOWER(token_ci, R, <<>>).
 
 token_ci(<<>>, T) -> T;
 token_ci(<< C, R/bits >>, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(token_ci, R, T)
-	end.
+	?LOWER(token_ci, R, T).
 
 -ifdef(TEST).
 prop_parse_sec_websocket_protocol_resp() ->
 	?FORALL(T,
 		token(),
-		?INLINE_LOWERCASE_BC(T) =:= parse_sec_websocket_protocol_resp(T)).
+		?LOWER(T) =:= parse_sec_websocket_protocol_resp(T)).
 
 parse_sec_websocket_protocol_resp_test_() ->
 	Tests = [
@@ -2781,20 +2554,14 @@ parse_sec_websocket_version_resp(SecWebSocketVersion) ->
 	nonempty(ws_version_list(SecWebSocketVersion, [])).
 
 ws_version_list(<<>>, Acc) -> lists:reverse(Acc);
-ws_version_list(<< $\s, R/bits >>, Acc) -> ws_version_list(R, Acc);
-ws_version_list(<< $\t, R/bits >>, Acc) -> ws_version_list(R, Acc);
-ws_version_list(<< $,, R/bits >>, Acc) -> ws_version_list(R, Acc);
+ws_version_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> ws_version_list(R, Acc);
 ws_version_list(<< C, R/bits >>, Acc) when ?IS_DIGIT(C) -> ws_version(R, Acc, C - $0).
 
-ws_version(<<>>, Acc, V) -> lists:reverse([V|Acc]);
-ws_version(<< $\s, R/bits >>, Acc, V) -> ws_version_list_sep(R, [V|Acc]);
-ws_version(<< $\t, R/bits >>, Acc, V) -> ws_version_list_sep(R, [V|Acc]);
-ws_version(<< $,, R/bits >>, Acc, V) -> ws_version_list(R, [V|Acc]);
-ws_version(<< C, R/bits >>, Acc, V) when ?IS_DIGIT(C) -> ws_version(R, Acc, V * 10 + C - $0).
+ws_version(<< C, R/bits >>, Acc, V) when ?IS_DIGIT(C) -> ws_version(R, Acc, V * 10 + C - $0);
+ws_version(R, Acc, V) -> ws_version_list_sep(R, [V|Acc]).
 
 ws_version_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-ws_version_list_sep(<< $\s, R/bits >>, Acc) -> ws_version_list_sep(R, Acc);
-ws_version_list_sep(<< $\t, R/bits >>, Acc) -> ws_version_list_sep(R, Acc);
+ws_version_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> ws_version_list_sep(R, Acc);
 ws_version_list_sep(<< $,, R/bits >>, Acc) -> ws_version_list(R, Acc).
 
 -ifdef(TEST).
@@ -2842,40 +2609,27 @@ parse_te(TE) ->
 	te_list(TE, no_trailers, []).
 
 te_list(<<>>, Trail, Acc) -> {Trail, lists:reverse(Acc)};
-te_list(<< $\s, R/bits >>, Trail, Acc) -> te_list(R, Trail, Acc);
-te_list(<< $\t, R/bits >>, Trail, Acc) -> te_list(R, Trail, Acc);
-te_list(<< $\,, R/bits >>, Trail, Acc) -> te_list(R, Trail, Acc);
+te_list(<< C, R/bits >>, Trail, Acc) when ?IS_WS_COMMA(C) -> te_list(R, Trail, Acc);
 te_list(<< "trailers", R/bits >>, Trail, Acc) -> te(R, Trail, Acc, <<"trailers">>);
 te_list(<< "compress", R/bits >>, Trail, Acc) -> te(R, Trail, Acc, <<"compress">>);
 te_list(<< "deflate", R/bits >>, Trail, Acc) -> te(R, Trail, Acc, <<"deflate">>);
 te_list(<< "gzip", R/bits >>, Trail, Acc) -> te(R, Trail, Acc, <<"gzip">>);
 te_list(<< C, R/bits >>, Trail, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(te, R, Trail, Acc, <<>>)
-	end.
+	?LOWER(te, R, Trail, Acc, <<>>).
 
-te(<<>>, _, Acc, T) when T =:= <<"trailers">> -> {trailers, lists:reverse(Acc)};
-te(<<>>, Trail, Acc, T) -> {Trail, lists:reverse([{T, 1000}|Acc])};
-te(<< $,, R/bits >>, _, Acc, T) when T =:= <<"trailers">> -> te_list(R, trailers, Acc);
-te(<< $,, R/bits >>, Trail, Acc, T) -> te_list(R, Trail, [{T, 1000}|Acc]);
+te(<<>>, _, Acc, <<"trailers">>) -> {trailers, lists:reverse(Acc)};
+te(<< $,, R/bits >>, _, Acc, <<"trailers">>) -> te_list(R, trailers, Acc);
 te(<< $;, R/bits >>, Trail, Acc, T) when T =/= <<"trailers">> -> te_before_weight(R, Trail, Acc, T);
-te(<< $\s, R/bits >>, _, Acc, T) when T =:= <<"trailers">> -> te_list_sep(R, trailers, Acc);
-te(<< $\s, R/bits >>, Trail, Acc, T) -> te_before_semicolon(R, Trail, Acc, T);
-te(<< $\t, R/bits >>, _, Acc, T) when T =:= <<"trailers">> -> te_list_sep(R, trailers, Acc);
-te(<< $\t, R/bits >>, Trail, Acc, T) -> te_before_semicolon(R, Trail, Acc, T);
+te(<< C, R/bits >>, _, Acc, <<"trailers">>) when ?IS_WS(C) -> te_list_sep(R, trailers, Acc);
 te(<< C, R/bits >>, Trail, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(te, R, Trail, Acc, T)
-	end.
+	?LOWER(te, R, Trail, Acc, T);
+te(R, Trail, Acc, T) -> te_param_sep(R, Trail, Acc, T).
 
-te_before_semicolon(<<>>, Trail, Acc, T) -> {Trail, lists:reverse([{T, 1000}|Acc])};
-te_before_semicolon(<< $,, R/bits >>, Trail, Acc, T) -> te_list(R, Trail, [{T, 1000}|Acc]);
-te_before_semicolon(<< $;, R/bits >>, Trail, Acc, T) -> te_before_weight(R, Trail, Acc, T);
-te_before_semicolon(<< $\s, R/bits >>, Trail, Acc, T) -> te_before_semicolon(R, Trail, Acc, T);
-te_before_semicolon(<< $\t, R/bits >>, Trail, Acc, T) -> te_before_semicolon(R, Trail, Acc, T).
+te_param_sep(<<>>, Trail, Acc, T) -> {Trail, lists:reverse([{T, 1000}|Acc])};
+te_param_sep(<< $,, R/bits >>, Trail, Acc, T) -> te_list(R, Trail, [{T, 1000}|Acc]);
+te_param_sep(<< C, R/bits >>, Trail, Acc, T) when ?IS_WS(C) -> te_param_sep(R, Trail, Acc, T).
 
-te_before_weight(<< $\s, R/bits >>, Trail, Acc, T) -> te_before_weight(R, Trail, Acc, T);
-te_before_weight(<< $\t, R/bits >>, Trail, Acc, T) -> te_before_weight(R, Trail, Acc, T);
+te_before_weight(<< C, R/bits >>, Trail, Acc, T) when ?IS_WS(C) -> te_before_weight(R, Trail, Acc, T);
 te_before_weight(<< $q, $=, R/bits >>, Trail, Acc, T) -> te_weight(R, Trail, Acc, T).
 
 te_weight(<< "1.000", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 1000}|Acc]);
@@ -2883,21 +2637,17 @@ te_weight(<< "1.00", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 100
 te_weight(<< "1.0", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 1000}|Acc]);
 te_weight(<< "1.", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 1000}|Acc]);
 te_weight(<< "1", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 1000}|Acc]);
-te_weight(<< "0.", A, B, C, R/bits >>, Trail, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9, C >= $0, C =< $9 ->
-		te_list_sep(R, Trail, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
-te_weight(<< "0.", A, B, R/bits >>, Trail, Acc, T)
-	when A >= $0, A =< $9, B >= $0, B =< $9 ->
-		te_list_sep(R, Trail, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
-te_weight(<< "0.", A, R/bits >>, Trail, Acc, T)
-	when A >= $0, A =< $9 ->
-		te_list_sep(R, Trail, [{T, (A - $0) * 100}|Acc]);
+te_weight(<< "0.", A, B, C, R/bits >>, Trail, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B), ?IS_DIGIT(C) ->
+	te_list_sep(R, Trail, [{T, (A - $0) * 100 + (B - $0) * 10 + (C - $0)}|Acc]);
+te_weight(<< "0.", A, B, R/bits >>, Trail, Acc, T) when ?IS_DIGIT(A), ?IS_DIGIT(B) ->
+	te_list_sep(R, Trail, [{T, (A - $0) * 100 + (B - $0) * 10}|Acc]);
+te_weight(<< "0.", A, R/bits >>, Trail, Acc, T) when ?IS_DIGIT(A) ->
+	te_list_sep(R, Trail, [{T, (A - $0) * 100}|Acc]);
 te_weight(<< "0.", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 0}|Acc]);
 te_weight(<< "0", R/bits >>, Trail, Acc, T) -> te_list_sep(R, Trail, [{T, 0}|Acc]).
 
 te_list_sep(<<>>, Trail, Acc) -> {Trail, lists:reverse(Acc)};
-te_list_sep(<< $\s, R/bits >>, Trail, Acc) -> te_list_sep(R, Trail, Acc);
-te_list_sep(<< $\t, R/bits >>, Trail, Acc) -> te_list_sep(R, Trail, Acc);
+te_list_sep(<< C, R/bits >>, Trail, Acc) when ?IS_WS(C) -> te_list_sep(R, Trail, Acc);
 te_list_sep(<< $,, R/bits >>, Trail, Acc) -> te_list(R, Trail, Acc).
 
 -ifdef(TEST).
@@ -2928,7 +2678,7 @@ prop_parse_te() ->
 		begin
 			{ResTrail, ResL} = parse_te(TE),
 			CheckedL = [begin
-				ResT =:= ?INLINE_LOWERCASE_BC(T)
+				ResT =:= ?LOWER(T)
 					andalso (ResW =:= W orelse (W =:= undefined andalso ResW =:= 1000))
 			end || {{T, W}, {ResT, ResW}} <- lists:zip(L, ResL)],
 			ResTrail =:= Trail andalso [true] =:= lists:usort(CheckedL)
@@ -2994,7 +2744,7 @@ prop_parse_transfer_encoding() ->
 		begin
 			<< _, TransferEncoding/binary >> = iolist_to_binary([[$,, C] || C <- L]),
 			ResL = parse_transfer_encoding(TransferEncoding),
-			CheckedL = [?INLINE_LOWERCASE_BC(Co) =:= ResC || {Co, ResC} <- lists:zip(L, ResL)],
+			CheckedL = [?LOWER(Co) =:= ResC || {Co, ResC} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
 		end).
 
@@ -3046,39 +2796,22 @@ parse_upgrade(Upgrade) ->
 	nonempty(protocol_list(Upgrade, [])).
 
 protocol_list(<<>>, Acc) -> lists:reverse(Acc);
-protocol_list(<< $\s, R/bits >>, Acc) -> protocol_list(R, Acc);
-protocol_list(<< $\t, R/bits >>, Acc) -> protocol_list(R, Acc);
-protocol_list(<< $,, R/bits >>, Acc) -> protocol_list(R, Acc);
+protocol_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> protocol_list(R, Acc);
 protocol_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(protocol_name, R, Acc, <<>>)
-	end.
+	?LOWER(protocol_name, R, Acc, <<>>).
 
-protocol_name(<<>>, Acc, P) -> lists:reverse([P|Acc]);
-protocol_name(<< $\s, R/bits >>, Acc, P) -> protocol_list_sep(R, [P|Acc]);
-protocol_name(<< $\t, R/bits >>, Acc, P) -> protocol_list_sep(R, [P|Acc]);
-protocol_name(<< $,, R/bits >>, Acc, P) -> protocol_list(R, [P|Acc]);
 protocol_name(<< $/, C, R/bits >>, Acc, P) ->
-	case C of
-		?INLINE_LOWERCASE(protocol_version, R, Acc, << P/binary, $/ >>)
-	end;
+	?LOWER(protocol_version, R, Acc, << P/binary, $/ >>);
 protocol_name(<< C, R/bits >>, Acc, P) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(protocol_name, R, Acc, P)
-	end.
+	?LOWER(protocol_name, R, Acc, P);
+protocol_name(R, Acc, P) -> protocol_list_sep(R, [P|Acc]).
 
-protocol_version(<<>>, Acc, P) -> lists:reverse([P|Acc]);
-protocol_version(<< $\s, R/bits >>, Acc, P) -> protocol_list_sep(R, [P|Acc]);
-protocol_version(<< $\t, R/bits >>, Acc, P) -> protocol_list_sep(R, [P|Acc]);
-protocol_version(<< $,, R/bits >>, Acc, P) -> protocol_list(R, [P|Acc]);
 protocol_version(<< C, R/bits >>, Acc, P) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(protocol_version, R, Acc, P)
-	end.
+	?LOWER(protocol_version, R, Acc, P);
+protocol_version(R, Acc, P) -> protocol_list_sep(R, [P|Acc]).
 
 protocol_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-protocol_list_sep(<< $\s, R/bits >>, Acc) -> protocol_list_sep(R, Acc);
-protocol_list_sep(<< $\t, R/bits >>, Acc) -> protocol_list_sep(R, Acc);
+protocol_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> protocol_list_sep(R, Acc);
 protocol_list_sep(<< $,, R/bits >>, Acc) -> protocol_list(R, Acc).
 
 -ifdef(TEST).
@@ -3093,7 +2826,7 @@ prop_parse_upgrade() ->
 		begin
 			<< _, Upgrade/binary >> = iolist_to_binary([[$,, P] || P <- L]),
 			ResL = parse_upgrade(Upgrade),
-			CheckedL = [?INLINE_LOWERCASE_BC(P) =:= ResP || {P, ResP} <- lists:zip(L, ResL)],
+			CheckedL = [?LOWER(P) =:= ResP || {P, ResP} <- lists:zip(L, ResL)],
 			[true] =:= lists:usort(CheckedL)
 		end).
 
@@ -3150,15 +2883,10 @@ parse_vary_error_test_() ->
 parse_www_authenticate(Authenticate) ->
 	nonempty(www_auth_list(Authenticate, [])).
 
--define(IS_WS(C), C =:= $\s orelse C =:= $\t).
--define(IS_WS_COMMA(C), ?IS_WS(C) orelse C =:= $,).
-
 www_auth_list(<<>>, Acc) -> lists:reverse(Acc);
 www_auth_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> www_auth_list(R, Acc);
 www_auth_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(www_auth_scheme, R, Acc, <<>>)
-	end.
+	?LOWER(www_auth_scheme, R, Acc, <<>>).
 
 www_auth_basic_before_realm(<< C, R/bits >>, Acc) when ?IS_WS(C) -> www_auth_basic_before_realm(R, Acc);
 www_auth_basic_before_realm(<< "realm=\"", R/bits >>, Acc) -> www_auth_basic(R, Acc, <<>>).
@@ -3175,9 +2903,7 @@ www_auth_scheme(<< C, R/bits >>, Acc, Scheme) when ?IS_WS(C) ->
 		_ -> www_auth_params_list(R, Acc, Scheme, [])
 	end;
 www_auth_scheme(<< C, R/bits >>, Acc, Scheme) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(www_auth_scheme, R, Acc, Scheme)
-	end.
+	?LOWER(www_auth_scheme, R, Acc, Scheme).
 
 www_auth_list_sep(<<>>, Acc) -> lists:reverse(Acc);
 www_auth_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> www_auth_list_sep(R, Acc);
@@ -3212,18 +2938,14 @@ www_auth_params_list(<< "stale=false", R/bits >>, Acc, Scheme, Params) ->
 www_auth_params_list(<< "stale=true", R/bits >>, Acc, Scheme, Params) ->
 	www_auth_params_list_sep(R, Acc, Scheme, [{<<"stale">>, <<"true">>}|Params]);
 www_auth_params_list(<< C, R/bits >>, Acc, Scheme, Params) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(www_auth_param, R, Acc, Scheme, Params, <<>>)
-	end.
+	?LOWER(www_auth_param, R, Acc, Scheme, Params, <<>>).
 
 www_auth_param(<< $=, $", R/bits >>, Acc, Scheme, Params, K) ->
 	www_auth_quoted(R, Acc, Scheme, Params, K, <<>>);
 www_auth_param(<< $=, C, R/bits >>, Acc, Scheme, Params, K) when ?IS_TOKEN(C) ->
 	www_auth_token(R, Acc, Scheme, Params, K, << C >>);
 www_auth_param(<< C, R/bits >>, Acc, Scheme, Params, K) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(www_auth_param, R, Acc, Scheme, Params, K)
-	end;
+	?LOWER(www_auth_param, R, Acc, Scheme, Params, K);
 www_auth_param(R, Acc, Scheme, Params, NewScheme) ->
 	www_auth_scheme(R, [{Scheme, lists:reverse(Params)}|Acc], NewScheme).
 
@@ -3338,42 +3060,24 @@ nonempty(L) when L =/= [] -> L.
 
 %% Parse a list of case sensitive tokens.
 token_list(<<>>, Acc) -> lists:reverse(Acc);
-token_list(<< $\s, R/bits >>, Acc) -> token_list(R, Acc);
-token_list(<< $\t, R/bits >>, Acc) -> token_list(R, Acc);
-token_list(<< $,, R/bits >>, Acc) -> token_list(R, Acc);
+token_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> token_list(R, Acc);
 token_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) -> token(R, Acc, << C >>).
 
-token(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-token(<< $\s, R/bits >>, Acc, T) -> token_list_sep(R, [T|Acc]);
-token(<< $\t, R/bits >>, Acc, T) -> token_list_sep(R, [T|Acc]);
-token(<< $,, R/bits >>, Acc, T) -> token_list(R, [T|Acc]);
-token(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> token(R, Acc, << T/binary, C >>).
+token(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> token(R, Acc, << T/binary, C >>);
+token(R, Acc, T) -> token_list_sep(R, [T|Acc]).
 
 token_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-token_list_sep(<< $\s, R/bits >>, Acc) -> token_list_sep(R, Acc);
-token_list_sep(<< $\t, R/bits >>, Acc) -> token_list_sep(R, Acc);
+token_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> token_list_sep(R, Acc);
 token_list_sep(<< $,, R/bits >>, Acc) -> token_list(R, Acc).
 
 %% Parse a list of case insensitive tokens.
 token_ci_list(<<>>, Acc) -> lists:reverse(Acc);
-token_ci_list(<< $\s, R/bits >>, Acc) -> token_ci_list(R, Acc);
-token_ci_list(<< $\t, R/bits >>, Acc) -> token_ci_list(R, Acc);
-token_ci_list(<< $,, R/bits >>, Acc) -> token_ci_list(R, Acc);
-token_ci_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(token_ci, R, Acc, <<>>)
-	end.
+token_ci_list(<< C, R/bits >>, Acc) when ?IS_WS_COMMA(C) -> token_ci_list(R, Acc);
+token_ci_list(<< C, R/bits >>, Acc) when ?IS_TOKEN(C) -> ?LOWER(token_ci, R, Acc, <<>>).
 
-token_ci(<<>>, Acc, T) -> lists:reverse([T|Acc]);
-token_ci(<< $\s, R/bits >>, Acc, T) -> token_ci_list_sep(R, [T|Acc]);
-token_ci(<< $\t, R/bits >>, Acc, T) -> token_ci_list_sep(R, [T|Acc]);
-token_ci(<< $,, R/bits >>, Acc, T) -> token_ci_list(R, [T|Acc]);
-token_ci(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) ->
-	case C of
-		?INLINE_LOWERCASE(token_ci, R, Acc, T)
-	end.
+token_ci(<< C, R/bits >>, Acc, T) when ?IS_TOKEN(C) -> ?LOWER(token_ci, R, Acc, T);
+token_ci(R, Acc, T) -> token_ci_list_sep(R, [T|Acc]).
 
 token_ci_list_sep(<<>>, Acc) -> lists:reverse(Acc);
-token_ci_list_sep(<< $\s, R/bits >>, Acc) -> token_ci_list_sep(R, Acc);
-token_ci_list_sep(<< $\t, R/bits >>, Acc) -> token_ci_list_sep(R, Acc);
+token_ci_list_sep(<< C, R/bits >>, Acc) when ?IS_WS(C) -> token_ci_list_sep(R, Acc);
 token_ci_list_sep(<< $,, R/bits >>, Acc) -> token_ci_list(R, Acc).

+ 7 - 7
src/cow_multipart.erl

@@ -192,7 +192,7 @@ parse_hd_name(<< C, Rest/bits >>, H, SoFar) ->
 		$: -> parse_hd_before_value(Rest, H, SoFar);
 		$\s -> parse_hd_name_ws(Rest, H, SoFar);
 		$\t -> parse_hd_name_ws(Rest, H, SoFar);
-		?INLINE_LOWERCASE(parse_hd_name, Rest, H, SoFar)
+		_ -> ?LOWER(parse_hd_name, Rest, H, SoFar)
 	end.
 
 parse_hd_name_ws(<< C, Rest/bits >>, H, Name) ->
@@ -546,7 +546,7 @@ parse_cd_type(<< C, Rest/bits >>, Acc) ->
 		$; -> {Acc, parse_before_param(Rest, [])};
 		$\s -> {Acc, parse_before_param(Rest, [])};
 		$\t -> {Acc, parse_before_param(Rest, [])};
-		?INLINE_LOWERCASE(parse_cd_type, Rest, Acc)
+		_ -> ?LOWER(parse_cd_type, Rest, Acc)
 	end.
 
 -ifdef(TEST).
@@ -600,7 +600,7 @@ horse_parse_content_disposition_inline() ->
 
 -spec parse_content_transfer_encoding(binary()) -> binary().
 parse_content_transfer_encoding(Bin) ->
-	?INLINE_LOWERCASE_BC(Bin).
+	?LOWER(Bin).
 
 -ifdef(TEST).
 parse_content_transfer_encoding_test_() ->
@@ -636,7 +636,7 @@ parse_content_type(Bin) ->
 parse_ct_type(<< C, Rest/bits >>, Acc) ->
 	case C of
 		$/ -> parse_ct_subtype(Rest, Acc, <<>>);
-		?INLINE_LOWERCASE(parse_ct_type, Rest, Acc)
+		_ -> ?LOWER(parse_ct_type, Rest, Acc)
 	end.
 
 parse_ct_subtype(<<>>, Type, Subtype) when Subtype =/= <<>> ->
@@ -646,7 +646,7 @@ parse_ct_subtype(<< C, Rest/bits >>, Type, Acc) ->
 		$; -> {Type, Acc, parse_before_param(Rest, [])};
 		$\s -> {Type, Acc, parse_before_param(Rest, [])};
 		$\t -> {Type, Acc, parse_before_param(Rest, [])};
-		?INLINE_LOWERCASE(parse_ct_subtype, Rest, Type, Acc)
+		_ -> ?LOWER(parse_ct_subtype, Rest, Type, Acc)
 	end.
 
 -ifdef(TEST).
@@ -710,7 +710,7 @@ parse_before_param(<< C, Rest/bits >>, Params) ->
 		$; -> parse_before_param(Rest, Params);
 		$\s -> parse_before_param(Rest, Params);
 		$\t -> parse_before_param(Rest, Params);
-		?INLINE_LOWERCASE(parse_param_name, Rest, Params, <<>>)
+		_ -> ?LOWER(parse_param_name, Rest, Params, <<>>)
 	end.
 
 parse_param_name(<<>>, Params, Acc) ->
@@ -718,7 +718,7 @@ parse_param_name(<<>>, Params, Acc) ->
 parse_param_name(<< C, Rest/bits >>, Params, Acc) ->
 	case C of
 		$= -> parse_param_value(Rest, Params, Acc);
-		?INLINE_LOWERCASE(parse_param_name, Rest, Params, Acc)
+		_ -> ?LOWER(parse_param_name, Rest, Params, Acc)
 	end.
 
 parse_param_value(<<>>, Params, Name) ->