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