Browse Source

Simplify multi-string encoding

The old implementation works by reversing the string twice, but there
is a far simpler solution:

Strings are 0 terminated: xxx\0yyy\0zzz\0. This makes a simple call to
binary:split/3 with a trim option wrong as it would trim empty
strings. E.g., the input xxx\0\0 would come out as [<<"xxx">>] and not
[<<"xxx">>, <<>>] as desired.

Observe that chopping off the last \0 makes the terminator into a
separator. This yields an optimization because we can create a
sub-binary for everything else and split on that.
Jesper Louis Andersen 6 years ago
parent
commit
7d8c030039
1 changed files with 7 additions and 2 deletions
  1. 7 2
      src/epgsql_wire.erl

+ 7 - 2
src/epgsql_wire.erl

@@ -45,8 +45,13 @@ decode_string(Bin) ->
 %% @doc decode multiple null-terminated string
 -spec decode_strings(binary()) -> [binary(), ...].
 decode_strings(Bin) ->
-    [<<>> | T] = lists:reverse(binary:split(Bin, <<0>>, [global])),
-    lists:reverse(T).
+    %% Assert the last byte is what we want it to be
+    %% Remove that byte from the Binary, so the zero
+    %% terminators are separators. Then apply
+    %% binary:split/3 directly on the remaining Subj
+    Sz = byte_size(Bin) - 1,
+    <<Subj:Sz/binary, 0>> = Bin,
+    binary:split(Subj, <<0>>, [global]).
 
 %% @doc decode error's field
 -spec decode_fields(binary()) -> [{byte(), binary()}].