paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / json / json.c
1 /*
2   This file is part of GNUnet
3   Copyright (C) 2014-2017 GNUnet e.V.
4
5   GNUnet is free software: you can redistribute it and/or modify it
6   under the terms of the GNU Affero General Public License as published
7   by the Free Software Foundation, either version 3 of the License,
8   or (at your option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Affero General Public License for more details.
14  
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file json/json.c
20  * @brief functions to parse JSON snippets
21  * @author Florian Dold
22  * @author Benedikt Mueller
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_json_lib.h"
27
28
29 /**
30  * Navigate and parse data in a JSON tree.  Tries to parse the @a root
31  * to find all of the values given in the @a spec.  If one of the
32  * entries in @a spec cannot be found or parsed, the name of the JSON
33  * field is returned in @a error_json_name, and the offset of the
34  * entry in @a spec is returned in @a error_line.
35  *
36  * @param root the JSON node to start the navigation at.
37  * @param spec parse specification array
38  * @param[out] error_json_name which JSON field was problematic
39  * @param[out] which index into @a spec did we encounter an error
40  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
41  */
42 int
43 GNUNET_JSON_parse (const json_t *root,
44                    struct GNUNET_JSON_Specification *spec,
45                    const char **error_json_name,
46                    unsigned int *error_line)
47 {
48   unsigned int i;
49   json_t *pos;
50
51   if (NULL == root)
52     return GNUNET_SYSERR;
53   for (i=0;NULL != spec[i].parser;i++)
54   {
55     if (NULL == spec[i].field)
56       pos = (json_t *) root;
57     else
58       pos = json_object_get (root,
59                              spec[i].field);
60     if ( (NULL == pos) ||
61          (GNUNET_OK !=
62           spec[i].parser (spec[i].cls,
63                           pos,
64                           &spec[i])) )
65     {
66       if (NULL != error_json_name)
67         *error_json_name = spec[i].field;
68       if (NULL != error_line)
69         *error_line = i;
70       GNUNET_JSON_parse_free (spec);
71       return GNUNET_SYSERR;
72     }
73   }
74   return GNUNET_OK; /* all OK! */
75 }
76
77
78 /**
79  * Frees all elements allocated during a #GNUNET_JSON_parse()
80  * operation.
81  *
82  * @param spec specification of the parse operation
83  */
84 void
85 GNUNET_JSON_parse_free (struct GNUNET_JSON_Specification *spec)
86 {
87   for (unsigned int i=0;NULL != spec[i].parser;i++)
88     if (NULL != spec[i].cleaner)
89       spec[i].cleaner (spec[i].cls,
90                        &spec[i]);
91 }
92
93
94 /**
95  * Set an option with a JSON value from the command line.
96  * A pointer to this function should be passed as part of the
97  * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options
98  * of this type.
99  *
100  * @param ctx command line processing context
101  * @param scls additional closure (will point to the 'json_t *')
102  * @param option name of the option
103  * @param value actual value of the option as a string.
104  * @return #GNUNET_OK if parsing the value worked
105  */
106 static int
107 set_json (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
108           void *scls,
109           const char *option,
110           const char *value)
111 {
112   json_t **json = scls;
113   json_error_t error;
114
115   *json = json_loads (value,
116                       JSON_REJECT_DUPLICATES,
117                       &error);
118   if (NULL == *json)
119   {
120     FPRINTF (stderr,
121              _("Failed to parse JSON in option `%s': %s (%s)\n"),
122              option,
123              error.text,
124              error.source);
125     return GNUNET_SYSERR;
126   }
127   return GNUNET_OK;
128 }
129
130
131 /**
132  * Allow user to specify a JSON input value.
133  *
134  * @param shortName short name of the option
135  * @param name long name of the option
136  * @param argumentHelp help text for the option argument
137  * @param description long help text for the option
138  * @param[out] val set to the JSON specified at the command line
139  */
140 struct GNUNET_GETOPT_CommandLineOption
141 GNUNET_JSON_getopt (char shortName,
142                     const char *name,
143                     const char *argumentHelp,
144                     const char *description,
145                     json_t **json)
146 {
147   struct GNUNET_GETOPT_CommandLineOption clo = {
148     .shortName =  shortName,
149     .name = name,
150     .argumentHelp = argumentHelp,
151     .description = description,
152     .require_argument = 1,
153     .processor = &set_json,
154     .scls = (void *) json
155   };
156
157   return clo;
158 }
159
160
161 /* end of json.c */