/modules/mod_base/filters/filter_slice.erl

https://code.google.com/p/zotonic/ · Erlang · 93 lines · 39 code · 14 blank · 40 comment · 0 complexity · 025ca8a63ffda790205158b451a2c629 MD5 · raw file

  1. %% @author Dmitrii Dimandt <dmitrii@dmitriid.com>
  2. %% @copyright 2011 Dmitrii Dimandt
  3. %% @doc 'slice' filter, get a range of elements from a list
  4. %% Copyright 2011 Dmitrii Dimandt
  5. %%
  6. %% Licensed under the Apache License, Version 2.0 (the "License");
  7. %% you may not use this file except in compliance with the License.
  8. %% You may obtain a copy of the License at
  9. %%
  10. %% http://www.apache.org/licenses/LICENSE-2.0
  11. %%
  12. %% Unless required by applicable law or agreed to in writing, software
  13. %% distributed under the License is distributed on an "AS IS" BASIS,
  14. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. %% See the License for the specific language governing permissions and
  16. %% limitations under the License.
  17. %
  18. % Given a list = [1,2,3,4,5,6,7,8,9,0]
  19. %
  20. % Get all elements from element M to element N:
  21. % {{ list|slice:[3,7] }} -> [3,4,5,6,7]
  22. % {{ list|slice:[3,-3] }} -> [3,4,5,6,7]
  23. % {{ list|slice:[-7,-3] }} -> [3,4,5,6,7]
  24. % {{ list|slice:[-7,7] }} -> [3,4,5,6,7]
  25. %
  26. % Get all elements except the first N:
  27. % {{ list|slice:[3,] }} -> [3,4,5,6,7,8,9,0]
  28. % {{ list|slice:[-7,] }} -> [3,4,5,6,7,8,9,0]
  29. %
  30. % Get all elements up to element N
  31. % {{ list|slice:[,3] }} -> [1,2,3]
  32. % {{ list|slice:[3] }} -> [1,2,3]
  33. %
  34. % Get all elements except the last N:
  35. % {{ list|slice:[,-3] }} -> [1,2,3,4,5,6,7]
  36. % {{ list|slice:[-3] }} -> [1,2,3,4,5,6,7]
  37. %
  38. % {{ list|slice:[M,N] }}, where N < M will return []
  39. % {{ list|slice:[,] }}, where N < M will return [1,2,3,4,5,6,7,8,9,0]
  40. %
  41. -module(filter_slice).
  42. -export([slice/3]).
  43. slice(undefined, _, _Context) ->
  44. undefined;
  45. slice(List, Slice, _Context) when is_list(List) ->
  46. slice1(List, Slice);
  47. slice(MaybeList, Slice, Context) ->
  48. slice1(erlydtl_runtime:to_list(MaybeList, Context), Slice).
  49. slice1(List, [undefined, undefined]) ->
  50. slice2(List, 1, length(List));
  51. slice1(List, [M, undefined]) ->
  52. slice2(List, M, length(List));
  53. slice1(List, [undefined, N]) ->
  54. N1 = if
  55. N < 0 -> length(List) + N;
  56. true -> N
  57. end,
  58. slice2(List, 1, N1);
  59. slice1(List, [M, N]) ->
  60. slice2(List, M, N);
  61. slice1(List, [M]) ->
  62. slice1(List, [undefined, M]);
  63. slice1(List, M) ->
  64. slice1(List, [undefined, z_convert:to_integer(M)]).
  65. slice2(List, M, N) ->
  66. M1 = if
  67. M =:= 0 -> throw({error, invalid_index});
  68. M < 0 -> length(List) + M;
  69. true -> M
  70. end,
  71. N1 = if
  72. N =:= 0 -> throw({error, invalid_index});
  73. N < 0 -> length(List) + N;
  74. true -> N
  75. end,
  76. if
  77. N1 < M1 -> [];
  78. true -> lists:sublist(List, M1, N1 - M1 + 1)
  79. end.