您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

218 行
6.2 KiB

  1. % This file is part of Jiffy released under the MIT license.
  2. % See the LICENSE file for more information.
  3. -module(jiffy).
  4. -export([decode/1, decode/2, encode/1, encode/2]).
  5. -define(NOT_LOADED, not_loaded(?LINE)).
  6. -compile([no_native]).
  7. -on_load(init/0).
  8. -type json_value() :: null
  9. | true
  10. | false
  11. | json_string()
  12. | json_number()
  13. | json_object()
  14. | json_array().
  15. -type json_array() :: [json_value()].
  16. -type json_string() :: atom() | binary().
  17. -type json_number() :: integer() | float().
  18. -ifdef(JIFFY_NO_MAPS).
  19. -type json_object() :: {[{json_string(),json_value()}]}.
  20. -else.
  21. -type json_object() :: {[{json_string(),json_value()}]}
  22. | #{json_string() => json_value()}.
  23. -endif.
  24. -type jiffy_decode_result() :: json_value()
  25. | {has_trailer, json_value(), binary()}.
  26. -type decode_option() :: return_maps
  27. | use_nil
  28. | return_trailer
  29. | {null_term, any()}
  30. | {bytes_per_iter, non_neg_integer()}
  31. | {bytes_per_red, non_neg_integer()}.
  32. -type encode_option() :: uescape
  33. | pretty
  34. | force_utf8
  35. | escape_forward_slashes
  36. | {bytes_per_iter, non_neg_integer()}
  37. | {bytes_per_red, non_neg_integer()}.
  38. -type decode_options() :: [decode_option()].
  39. -type encode_options() :: [encode_option()].
  40. -export_type([json_value/0, jiffy_decode_result/0]).
  41. -spec decode(iolist() | binary()) -> jiffy_decode_result().
  42. decode(Data) ->
  43. decode(Data, []).
  44. -spec decode(iolist() | binary(), decode_options()) -> json_value().
  45. decode(Data, Opts) when is_binary(Data), is_list(Opts) ->
  46. case nif_decode_init(Data, Opts) of
  47. {error, _} = Error ->
  48. throw(Error);
  49. {partial, EJson} ->
  50. finish_decode(EJson);
  51. {iter, Decoder, Val, Objs, Curr} ->
  52. decode_loop(Data, Decoder, Val, Objs, Curr);
  53. EJson ->
  54. EJson
  55. end;
  56. decode(Data, Opts) when is_list(Data) ->
  57. decode(iolist_to_binary(Data), Opts).
  58. -spec encode(json_value()) -> iolist().
  59. encode(Data) ->
  60. encode(Data, []).
  61. -spec encode(json_value(), encode_options()) -> iolist().
  62. encode(Data, Options) ->
  63. ForceUTF8 = lists:member(force_utf8, Options),
  64. case nif_encode_init(Data, Options) of
  65. {error, {invalid_string, _}} when ForceUTF8 == true ->
  66. FixedData = jiffy_utf8:fix(Data),
  67. encode(FixedData, Options -- [force_utf8]);
  68. {error, _} = Error ->
  69. throw(Error);
  70. {partial, IOData} ->
  71. finish_encode(IOData, []);
  72. {iter, Encoder, Stack, IOBuf} ->
  73. encode_loop(Data, Options, Encoder, Stack, IOBuf);
  74. IOData ->
  75. IOData
  76. end.
  77. finish_decode({bignum, Value}) ->
  78. list_to_integer(binary_to_list(Value));
  79. finish_decode({bignum_e, Value}) ->
  80. {IVal, EVal} = case string:to_integer(binary_to_list(Value)) of
  81. {I, [$e | ExpStr]} ->
  82. {E, []} = string:to_integer(ExpStr),
  83. {I, E};
  84. {I, [$E | ExpStr]} ->
  85. {E, []} = string:to_integer(ExpStr),
  86. {I, E}
  87. end,
  88. IVal * math:pow(10, EVal);
  89. finish_decode({bigdbl, Value}) ->
  90. list_to_float(binary_to_list(Value));
  91. finish_decode({Pairs}) when is_list(Pairs) ->
  92. finish_decode_obj(Pairs, []);
  93. finish_decode(Vals) when is_list(Vals) ->
  94. finish_decode_arr(Vals, []);
  95. finish_decode(Val) ->
  96. maybe_map(Val).
  97. -ifndef(JIFFY_NO_MAPS).
  98. maybe_map(Obj) when is_map(Obj) ->
  99. maps:map(fun finish_decode_map/2, Obj);
  100. maybe_map(Val) ->
  101. Val.
  102. finish_decode_map(_, V) ->
  103. finish_decode(V).
  104. -else.
  105. maybe_map(Val) ->
  106. Val.
  107. -endif.
  108. finish_decode_obj([], Acc) ->
  109. {lists:reverse(Acc)};
  110. finish_decode_obj([{K, V} | Pairs], Acc) ->
  111. finish_decode_obj(Pairs, [{K, finish_decode(V)} | Acc]).
  112. finish_decode_arr([], Acc) ->
  113. lists:reverse(Acc);
  114. finish_decode_arr([V | Vals], Acc) ->
  115. finish_decode_arr(Vals, [finish_decode(V) | Acc]).
  116. finish_encode([], Acc) ->
  117. %% No reverse! The NIF returned us
  118. %% the pieces in reverse order.
  119. Acc;
  120. finish_encode([<<_/binary>>=B | Rest], Acc) ->
  121. finish_encode(Rest, [B | Acc]);
  122. finish_encode([Val | Rest], Acc) when is_integer(Val) ->
  123. Bin = list_to_binary(integer_to_list(Val)),
  124. finish_encode(Rest, [Bin | Acc]);
  125. finish_encode([InvalidEjson | _], _) ->
  126. throw({error, {invalid_ejson, InvalidEjson}});
  127. finish_encode(_, _) ->
  128. throw({error, invalid_ejson}).
  129. init() ->
  130. PrivDir = case code:priv_dir(?MODULE) of
  131. {error, _} ->
  132. EbinDir = filename:dirname(code:which(?MODULE)),
  133. AppPath = filename:dirname(EbinDir),
  134. filename:join(AppPath, "priv");
  135. Path ->
  136. Path
  137. end,
  138. erlang:load_nif(filename:join(PrivDir, "jiffy"), 0).
  139. decode_loop(Data, Decoder, Val, Objs, Curr) ->
  140. case nif_decode_iter(Data, Decoder, Val, Objs, Curr) of
  141. {error, _} = Error ->
  142. throw(Error);
  143. {partial, EJson} ->
  144. finish_decode(EJson);
  145. {iter, NewDecoder, NewVal, NewObjs, NewCurr} ->
  146. decode_loop(Data, NewDecoder, NewVal, NewObjs, NewCurr);
  147. EJson ->
  148. EJson
  149. end.
  150. encode_loop(Data, Options, Encoder, Stack, IOBuf) ->
  151. ForceUTF8 = lists:member(force_utf8, Options),
  152. case nif_encode_iter(Encoder, Stack, IOBuf) of
  153. {error, {invalid_string, _}} when ForceUTF8 == true ->
  154. FixedData = jiffy_utf8:fix(Data),
  155. encode(FixedData, Options -- [force_utf8]);
  156. {error, _} = Error ->
  157. throw(Error);
  158. {partial, IOData} ->
  159. finish_encode(IOData, []);
  160. {iter, NewEncoder, NewStack, NewIOBuf} ->
  161. encode_loop(Data, Options, NewEncoder, NewStack, NewIOBuf);
  162. IOData ->
  163. IOData
  164. end.
  165. not_loaded(Line) ->
  166. erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}).
  167. nif_decode_init(_Data, _Opts) ->
  168. ?NOT_LOADED.
  169. nif_decode_iter(_Data, _Decoder, _, _, _) ->
  170. ?NOT_LOADED.
  171. nif_encode_init(_Data, _Options) ->
  172. ?NOT_LOADED.
  173. nif_encode_iter(_Encoder, _Stack, _IoList) ->
  174. ?NOT_LOADED.