File 2201-Add-map-conversion-functions-to-proplists.patch of Package erlang

From 000eef428f7c239b3c4e76b23ea3c578d6bf5219 Mon Sep 17 00:00:00 2001
From: Maria-12648430 <maria-12648430@gmx.net>
Date: Fri, 11 Dec 2020 17:03:56 +0100
Subject: [PATCH 1/2] Add map conversion functions to proplists

---
 lib/stdlib/doc/src/proplists.xml    | 32 ++++++++++++++
 lib/stdlib/src/proplists.erl        | 57 ++++++++++++++++++++++++-
 lib/stdlib/test/proplists_SUITE.erl | 65 ++++++++++++++++++++++++++++-
 3 files changed, 151 insertions(+), 3 deletions(-)

diff --git a/lib/stdlib/doc/src/proplists.xml b/lib/stdlib/doc/src/proplists.xml
index f59b6eda17..05c02cc3be 100644
--- a/lib/stdlib/doc/src/proplists.xml
+++ b/lib/stdlib/doc/src/proplists.xml
@@ -137,6 +137,14 @@ expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])</code>
       </desc>
     </func>
 
+    <func>
+      <name name="from_map" arity="1" since=""/>
+      <fsummary></fsummary>
+      <desc>
+        <p>Converts the map <c><anno>Map</anno></c> to a property list.</p>
+      </desc>
+    </func>
+
     <func>
       <name name="get_all_values" arity="2" since=""/>
       <fsummary></fsummary>
@@ -364,6 +372,30 @@ split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])</code>
       </desc>
     </func>
 
+    <func>
+      <name name="to_map" arity="1" since=""/>
+      <fsummary></fsummary>
+      <desc>
+        <p>Converts the property list <c><anno>List</anno></c> to a map.</p>
+        <p>Shorthand atom values in <c><anno>List</anno></c> will be expanded
+          to an association of the form <c>Atom => true</c>. Tuples of the
+          form <c>{Key, Value}</c> in <c><anno>List</anno></c> will be
+          converted to an association of the form <c>Key => Value</c>.
+          Anything else will be silently ignored.</p>
+        <p>If the same key appears in <c><anno>List</anno></c> multiple
+          times, the value of the one appearing nearest to the head of
+          <c><anno>List</anno></c> will be in the result map, that is
+          the value that would be returned by a call to
+          <c>get_value(Key, List)</c>.</p>
+        <p><em>Example:</em></p>
+        <code type="none">
+to_map([a, {b, 1}, {c, 2}, {c, 3}])</code>
+        <p>returns:</p>
+        <code type="none">
+#{a => true, b => 1, c => 2}</code>
+      </desc>
+    </func>
+
     <func>
       <name name="unfold" arity="1" since=""/>
       <fsummary></fsummary>
diff --git a/lib/stdlib/src/proplists.erl b/lib/stdlib/src/proplists.erl
index 9216c3bdb3..b92982dae0 100644
--- a/lib/stdlib/src/proplists.erl
+++ b/lib/stdlib/src/proplists.erl
@@ -35,7 +35,7 @@
 	 lookup_all/2, is_defined/2, get_value/2, get_value/3,
 	 get_all_values/2, append_values/2, get_bool/2, get_keys/1,
 	 delete/2, substitute_aliases/2, substitute_negations/2,
-	 expand/2, normalize/2, split/2]).
+	 expand/2, normalize/2, split/2, from_map/1, to_map/1]).
 
 %% ---------------------------------------------------------------------
 
@@ -668,3 +668,58 @@ split([], Store, Rest) ->
 
 maps_prepend(Key, Val, Dict) ->
     Dict#{Key := [Val | map_get(Key, Dict)]}.
+
+%% ---------------------------------------------------------------------
+
+%% @doc Converts the property list <code>List</code> to a map.
+%%
+%% Shorthand atom values in <code>List</code> will be expanded to an
+%% association of the form <code>Atom => true</code>. Tuples of the
+%% form <code>{Key, Value}</code> in <code>List</code> will be
+%% converted to an association of the form <code>Key => Value</code>.
+%% Anything else will be silently ignored.
+%%
+%% If the same key appears in <code>List</code> multiple times, the
+%% value of the one appearing nearest to the head of <code>List</code>
+%% will be in the result map, that is the value that would be returned
+%% by a call to <code>get_value/2</code> with this key.
+%%
+%% <p>Example:<pre>
+%% to_map([a, {b, 1}, {c, 2}, {c, 3}])</pre>
+%% returns<pre>
+%% #{a => true, b => 1, c => 2}</pre>
+%% </p>
+
+-spec to_map(List) -> Map when
+      List :: [Shorthand | {Key, Value} | term()],
+      Map :: #{Shorthand => 'true', Key => Value},
+      Shorthand :: atom(),
+      Key :: term(),
+      Value :: term().
+
+to_map(List) ->
+    lists:foldr(
+        fun
+            ({K, V}, M) ->
+                M#{K => V};
+            (T, M) when 1 =< tuple_size(T) ->
+                maps:remove(element(1, T), M);
+            (K, M) when is_atom(K) ->
+                M#{K => true};
+            (_, M) ->
+                M
+        end,
+        #{},
+        List
+    ).
+
+%% @doc Converts the map <code>Map</code> to a property list.
+
+-spec from_map(Map) -> List when
+    Map :: #{Key => Value},
+    List :: [{Key, Value}],
+    Key :: term(),
+    Value :: term().
+
+from_map(Map) ->
+    maps:to_list(Map).
diff --git a/lib/stdlib/test/proplists_SUITE.erl b/lib/stdlib/test/proplists_SUITE.erl
index 600fb8845e..64c5e60125 100644
--- a/lib/stdlib/test/proplists_SUITE.erl
+++ b/lib/stdlib/test/proplists_SUITE.erl
@@ -23,7 +23,7 @@
 -export([all/0, suite/0,groups/0, init_per_suite/1, end_per_suite/1,
          init_per_group/2, end_per_group/2,
 	 init_per_testcase/2, end_per_testcase/2,
-         examples/1]).
+         examples/1, map_conversion/1]).
 
 init_per_testcase(_Case, Config) ->
     Config.
@@ -36,7 +36,7 @@ suite() ->
      {timetrap,{minutes,5}}].
 
 all() ->
-    [examples].
+    [examples, map_conversion].
 
 groups() ->
     [].
@@ -77,4 +77,65 @@ examples(_Config) ->
     NegListRes = [{foo, false}, {foo, false}, foo, foo, foo],
     NegListRes = proplists:substitute_negations([{no_foo, foo}], NegList),
 
+    true = #{a => true, b => 1, c => 2} =:= proplists:to_map([a, {b, 1}, {c, 2}, {c, 3}]),
+
+    ok.
+
+map_conversion(_Config) ->
+    %% Simple tests.
+    true = #{} =:= proplists:to_map([]),
+    true = #{a => true, b => true} =:= proplists:to_map([a, b]),
+    true = #{a => true, b => true} =:= proplists:to_map([b, a]),
+    true = #{a => 1, b => true} =:= proplists:to_map([{a, 1}, b]),
+    true = #{a => 1, b => true} =:= proplists:to_map([b, {a, 1}]),
+    true = #{a => 1, b => 2} =:= proplists:to_map([{a, 1}, {b, 2}]),
+    true = #{a => 1, b => 2} =:= proplists:to_map([{b, 2}, {a, 1}]),
+    true = #{b => true} =:= proplists:to_map(["a", b]),
+    true = #{b => true} =:= proplists:to_map([b, "a"]),
+    true = #{b => true} =:= proplists:to_map([{a}, b]),
+    true = #{b => true} =:= proplists:to_map([b, {a}]),
+    true = #{b => true} =:= proplists:to_map([{a, 1, 2}, b]),
+    true = #{b => true} =:= proplists:to_map([b, {a, 1, 2}]),
+
+    %% Ensure that maps:get/3 using the created map yields the same
+    %% results as proplists:get_value/3 on the original proplist does,
+    %% and that proplists:get_value/3 on a proplist created from the
+    %% map yields the same results as proplists:get_value/3 on the
+    %% original proplist, ie they either all return the same `Value',
+    %% or they all return the `Default' given as respective third argument.
+    Default1 = make_ref(),
+    Default2 = make_ref(),
+    Default3 = make_ref(),
+    InList=[a, b, {a, 1}, {}, {a}, {a, 1, 2}, "foo"],
+    lists:foreach(
+        fun (L1) ->
+            LKs = proplists:get_keys(L1),
+            M = proplists:to_map(L1),
+            L2 = proplists:from_map(M),
+            [] = maps:keys(M) -- LKs,
+            [] = proplists:get_keys(L2) -- LKs, 
+            lists:foreach(
+                fun (K) ->
+                    case
+                        {
+                            maps:get(K, M, Default1),
+                            proplists:get_value(K, L1, Default2),
+                            proplists:get_value(K, L2, Default3)
+                        }
+                    of
+                        {V, V, V} -> true;
+                        {Default1, Default2, Default3} -> true
+                    end
+                end,
+                LKs
+            )
+        end,
+        [[A, B, C, D, E, F, G] || A <- InList,
+                                  B <- InList -- [A],
+                                  C <- InList -- [A, B],
+                                  D <- InList -- [A, B, C],
+                                  E <- InList -- [A, B, C, D],
+                                  F <- InList -- [A, B, C, D, E],
+                                  G <- InList -- [A, B, C, D, E, F]]
+    ),
     ok.
-- 
2.26.2

openSUSE Build Service is sponsored by