1%% The MIT License
2
3%% Copyright (c) 2010-2015 Alisdair Sullivan <alisdairsullivan@yahoo.ca>
4
5%% Permission is hereby granted, free of charge, to any person obtaining a copy
6%% of this software and associated documentation files (the "Software"), to deal
7%% in the Software without restriction, including without limitation the rights
8%% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9%% copies of the Software, and to permit persons to whom the Software is
10%% furnished to do so, subject to the following conditions:
11
12%% The above copyright notice and this permission notice shall be included in
13%% all copies or substantial portions of the Software.
14
15%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21%% THE SOFTWARE.
22
23
24-module(jsx_consult).
25
26-export([consult/2]).
27-export([init/1, reset/1, handle_event/2]).
28
29
30-record(config, {
31    labels = binary,
32    return_maps = false
33}).
34
35-type config() :: list().
36-export_type([config/0]).
37
38-ifndef(maps_support).
39-type json_value() :: list(json_value())
40    | list({binary() | atom(), json_value()})
41    | true
42    | false
43    | null
44    | integer()
45    | float()
46    | binary().
47-endif.
48
49-ifdef(maps_support).
50-type json_value() :: list(json_value())
51    | map()
52    | true
53    | false
54    | null
55    | integer()
56    | float()
57    | binary().
58-endif.
59
60
61-ifdef(maps_always).
62opts(Opts) -> [return_maps, multi_term] ++ Opts.
63-endif.
64-ifndef(maps_always).
65opts(Opts) -> [multi_term] ++ Opts.
66-endif.
67
68-spec consult(File::file:name_all(), Config::config()) -> [json_value()].
69
70consult(File, Config) when is_list(Config) ->
71    case file:read_file(File) of
72      {ok, Bin}  ->
73          {Final, _, _} = (jsx:decoder(
74              ?MODULE,
75              opts(Config),
76              jsx_config:extract_config(opts(Config))
77          ))(Bin),
78          lists:reverse(Final);
79      {error, _} -> erlang:error(badarg)
80    end.
81
82
83-type state() :: {list(), #config{}}.
84-spec init(Config::proplists:proplist()) -> state().
85
86init(Config) -> {[], Config, jsx_to_term:start_term(Config)}.
87
88
89-spec reset(State::state()) -> state().
90
91reset({Acc, Config, _}) -> {Acc, Config, jsx_to_term:start_term(Config)}.
92
93
94-spec handle_event(Event::any(), State::state()) -> state().
95
96handle_event(end_json, {Acc, Config, State}) ->
97    {[jsx_to_term:get_value(State)] ++ Acc, Config, State};
98handle_event(Event, {Acc, Config, State}) ->
99    {Acc, Config, jsx_to_term:handle_event(Event, State)}.
100