VPP-1474: fix coverity warning
[vpp.git] / src / plugins / perfmon / parse_util.c
1 /*
2  * parse_util.c - halfhearted json parser
3  *
4  * Copyright (c) 2018 Cisco Systems and/or its affiliates
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <perfmon/perfmon.h>
19 #include <vppinfra/unix.h>
20
21 typedef enum
22 {
23   STATE_START,
24   STATE_READ_NAME,
25   STATE_READ_VALUE,
26 } parse_state_t;
27
28 static u8 *
29 downcase (u8 * s)
30 {
31   u8 *rv = 0;
32   u8 c;
33   int i;
34
35   for (i = 0; i < vec_len (s); i++)
36     {
37       c = s[i];
38       if (c >= 'A' && c <= 'Z')
39         c = c + ('a' - 'A');
40       vec_add1 (rv, c);
41     }
42   return (rv);
43 }
44
45 uword *
46 perfmon_parse_table (perfmon_main_t * pm, char *path, char *table_name)
47 {
48   u8 *cp;
49   u8 *event_name;
50   int state = STATE_START;
51   uword *ht;
52   name_value_pair_t *nvp = 0;
53   name_value_pair_t **nvps = 0;
54   u8 *v;
55   int i;
56   u8 *json_filename;
57   clib_error_t *error;
58
59   /* Create the name/value hash table in any case... */
60   ht = hash_create_string (0, sizeof (uword));
61
62   json_filename = format (0, "%s/%s%c", path, table_name, 0);
63
64   vlib_log_debug (pm->log_class, "Try to read perfmon events from %s",
65                   json_filename);
66
67   error = unix_proc_file_contents ((char *) json_filename, &cp);
68
69   if (error)
70     {
71       vlib_log_err (pm->log_class,
72                     "Failed to read CPU-specific counter table");
73       vlib_log_err (pm->log_class,
74                     "Download from https://download.01.org/perfmon, "
75                     "and install as %s", json_filename);
76       vec_free (json_filename);
77       clib_error_report (error);
78       return ht;
79     }
80   vlib_log_debug (pm->log_class, "Read OK, parse the event table...");
81   vec_free (json_filename);
82
83 again:
84   while (*cp)
85     {
86       switch (state)
87         {
88         case STATE_START:
89           while (*cp && *cp != '{' && *cp != '}' && *cp != ',')
90             cp++;
91           if (*cp == 0)
92             goto done;
93
94           /* Look for a new event */
95           if (*cp == '{')
96             {
97               if (*cp == 0)
98                 {
99                 error:
100                   clib_warning ("parse fail");
101                   hash_free (ht);
102                   return 0;
103                 }
104               cp++;
105               state = STATE_READ_NAME;
106               goto again;
107             }
108           else if (*cp == '}')  /* end of event */
109             {
110               /* Look for the "EventName" nvp */
111               for (i = 0; i < vec_len (nvps); i++)
112                 {
113                   nvp = nvps[i];
114                   if (!strncmp ((char *) nvp->name, "EventName", 9))
115                     {
116                       event_name = nvp->value;
117                       goto found;
118                     }
119                 }
120               /* no name? */
121               for (i = 0; i < vec_len (nvps); i++)
122                 {
123                   vec_free (nvps[i]->name);
124                   vec_free (nvps[i]->value);
125                 }
126               vec_free (nvps);
127               cp++;
128               goto again;
129
130             found:
131               event_name = downcase (event_name);
132               hash_set_mem (ht, event_name, nvps);
133               nvp = 0;
134               nvps = 0;
135               cp++;
136               goto again;
137             }
138           else if (*cp == ',')  /* punctuation */
139             {
140               cp++;
141               goto again;
142             }
143           else                  /* should never happen... */
144             cp++;
145           goto again;
146
147         case STATE_READ_NAME:
148           vec_validate (nvp, 0);
149           v = 0;
150           while (*cp && *cp != '"')
151             cp++;
152
153           if (*cp == 0)
154             {
155               vec_free (nvp);
156               goto error;
157             }
158
159           cp++;
160           while (*cp && *cp != '"')
161             {
162               vec_add1 (v, *cp);
163               cp++;
164             }
165           if (*cp == 0)
166             {
167               vec_free (v);
168               goto error;
169             }
170           cp++;
171           vec_add1 (v, 0);
172           nvp->name = v;
173           state = STATE_READ_VALUE;
174           goto again;
175
176         case STATE_READ_VALUE:
177           while (*cp && *cp != ':')
178             cp++;
179           if (*cp == 0)
180             {
181               vec_free (nvp->name);
182               goto error;
183             }
184           while (*cp && *cp != '"')
185             cp++;
186           if (*cp == 0)
187             {
188               vec_free (nvp->name);
189               goto error;
190             }
191           else
192             cp++;
193           v = 0;
194           while (*cp && *cp != '"')
195             {
196               vec_add1 (v, *cp);
197               cp++;
198             }
199           if (*cp == 0)
200             {
201               vec_free (nvp->name);
202               vec_free (v);
203               goto error;
204             }
205           vec_add1 (v, 0);
206           nvp->value = v;
207           vec_add1 (nvps, nvp);
208           while (*cp && *cp != ',' && *cp != '}')
209             cp++;
210           if (*cp == 0)
211             {
212               vec_free (nvp->name);
213               vec_free (nvp->value);
214               goto error;
215             }
216           else if (*cp == '}')
217             state = STATE_START;
218           else
219             {
220               cp++;
221               state = STATE_READ_NAME;
222             }
223           nvp = 0;
224           goto again;
225         }
226     }
227
228 done:
229   return (ht);
230 }
231
232 /*
233  * fd.io coding-style-patch-verification: ON
234  *
235  * Local Variables:
236  * eval: (c-set-style "gnu")
237  * End:
238  */