Skip to content

Commit c2ef39c

Browse files
committed
parser-json-simple: separate module for SimpleTreeDecoder
1 parent ee474a9 commit c2ef39c

File tree

4 files changed

+231
-166
lines changed

4 files changed

+231
-166
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ add_library(cs STATIC
7676
parser-cov.cc
7777
parser-gcc.cc
7878
parser-json.cc
79+
parser-json-simple.cc
7980
parser-xml.cc
8081
shared-string.cc
8182
version.cc

src/parser-json-simple.cc

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (C) 2012-2022 Red Hat, Inc.
3+
*
4+
* This file is part of csdiff.
5+
*
6+
* csdiff is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* any later version.
10+
*
11+
* csdiff is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "parser-json-simple.hh"
21+
22+
#include "parser-cov.hh" // for KeyEventDigger
23+
24+
#include <set>
25+
26+
struct SimpleTreeDecoder::Private {
27+
enum ENodeKind {
28+
NK_DEFECT,
29+
NK_EVENT,
30+
NK_LAST
31+
};
32+
33+
void reportUnknownNodes(ENodeKind, const pt::ptree &) const;
34+
35+
typedef std::set<std::string> TNodeSet;
36+
typedef std::vector<TNodeSet> TNodeStore;
37+
38+
InStream &input;
39+
TNodeStore nodeStore;
40+
KeyEventDigger keDigger;
41+
42+
Private(InStream &input);
43+
};
44+
45+
SimpleTreeDecoder::Private::Private(InStream &input):
46+
input(input)
47+
{
48+
if (input.silent())
49+
// skip initialization of nodeStore_ because no lookup will ever happen
50+
return;
51+
52+
this->nodeStore.resize(NK_LAST);
53+
54+
// known per-defect subnodes
55+
this->nodeStore[NK_DEFECT] = {
56+
"annotation",
57+
"checker",
58+
"cwe",
59+
"defect_id",
60+
"events",
61+
"function",
62+
"imp",
63+
"key_event_idx",
64+
"language",
65+
"tool",
66+
};
67+
68+
// known per-event subnodes
69+
this->nodeStore[NK_EVENT] = {
70+
"column",
71+
"event",
72+
"file_name",
73+
"line",
74+
"message",
75+
"verbosity_level",
76+
};
77+
}
78+
79+
void SimpleTreeDecoder::Private::reportUnknownNodes(
80+
const ENodeKind nk,
81+
const pt::ptree &node)
82+
const
83+
{
84+
if (this->input.silent())
85+
return;
86+
87+
const TNodeSet &nodeSet = this->nodeStore[nk];
88+
89+
for (const pt::ptree::value_type &item : node) {
90+
const std::string &name = item.first;
91+
if (nodeSet.end() == nodeSet.find(name))
92+
std::cerr << this->input.fileName()
93+
<< ": warning: unknown JSON node: " << name
94+
<< std::endl;
95+
}
96+
}
97+
98+
SimpleTreeDecoder::SimpleTreeDecoder(InStream &input):
99+
d(new Private(input))
100+
{
101+
}
102+
103+
SimpleTreeDecoder::~SimpleTreeDecoder() = default;
104+
105+
void SimpleTreeDecoder::readScanProps(
106+
TScanProps *pDst,
107+
const pt::ptree *root)
108+
{
109+
const pt::ptree emp;
110+
const pt::ptree &scanNode =
111+
root->get_child_optional("scan").get_value_or(emp);
112+
113+
for (const pt::ptree::value_type &item : scanNode)
114+
(*pDst)[item.first] = item.second.data();
115+
}
116+
117+
bool SimpleTreeDecoder::readNode(Defect *def)
118+
{
119+
// move the iterator after we get the current position
120+
const pt::ptree *pNode = this->nextNode();
121+
if (!pNode)
122+
// failed initialization or EOF
123+
return false;
124+
125+
const pt::ptree &defNode = *pNode;
126+
127+
d->reportUnknownNodes(Private::NK_DEFECT, defNode);
128+
129+
// the checker field is mandatory
130+
def->checker = defNode.get<std::string>("checker");
131+
132+
bool verbosityLevelNeedsInit = false;
133+
134+
// read the events
135+
TEvtList &evtListDst = def->events;
136+
const pt::ptree &evtListSrc = defNode.get_child("events");
137+
for (const pt::ptree::value_type &evtItem : evtListSrc) {
138+
const pt::ptree &evtNode = evtItem.second;
139+
d->reportUnknownNodes(Private::NK_EVENT, evtNode);
140+
141+
DefEvent evt;
142+
evt.fileName = valueOf<std::string >(evtNode, "file_name" , "");
143+
evt.line = valueOf<int >(evtNode, "line" , 0);
144+
evt.column = valueOf<int >(evtNode, "column" , 0);
145+
evt.event = valueOf<std::string >(evtNode, "event" , "");
146+
evt.msg = valueOf<std::string >(evtNode, "message" , "");
147+
evt.verbosityLevel = valueOf<int>(evtNode, "verbosity_level" , -1);
148+
if (-1 == evt.verbosityLevel)
149+
verbosityLevelNeedsInit = true;
150+
151+
evtListDst.push_back(evt);
152+
}
153+
154+
// read "defect_id", "cwe", and "function" if available
155+
def->defectId = valueOf<int> (defNode, "defect_id", 0);
156+
def->cwe = valueOf<int> (defNode, "cwe" , 0);
157+
def->imp = valueOf<int> (defNode, "imp" , 0);
158+
def->function = valueOf<std::string>(defNode, "function", "");
159+
def->language = valueOf<std::string>(defNode, "language", "");
160+
def->tool = valueOf<std::string>(defNode, "tool", "");
161+
162+
if (defNode.not_found() == defNode.find("key_event_idx")) {
163+
// key event not specified, try to guess it
164+
if (!d->keDigger.guessKeyEvent(def))
165+
throw pt::ptree_error("failed to guess key event");
166+
}
167+
else {
168+
// use the provided key_event_idx unless it is out of range
169+
const int cntEvents = evtListDst.size();
170+
const int defKeyEvent = defNode.get<int>("key_event_idx");
171+
if (0 <= defKeyEvent && defKeyEvent < cntEvents)
172+
def->keyEventIdx = defKeyEvent;
173+
else
174+
throw pt::ptree_error("key event out of range");
175+
}
176+
177+
if (verbosityLevelNeedsInit)
178+
// missing or incomplete verbosity_level, initialize it over
179+
d->keDigger.initVerbosity(def);
180+
181+
// read annotation if available
182+
def->annotation = valueOf<std::string>(defNode, "annotation", "");
183+
184+
return true;
185+
}
186+

src/parser-json-simple.hh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (C) 2012-2022 Red Hat, Inc.
3+
*
4+
* This file is part of csdiff.
5+
*
6+
* csdiff is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* any later version.
10+
*
11+
* csdiff is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with csdiff. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#ifndef H_GUARD_PARSER_JSON_SIMPLE_H
21+
#define H_GUARD_PARSER_JSON_SIMPLE_H
22+
23+
#include "abstract-tree.hh"
24+
25+
/// tree decoder of the native JSON format of csdiff
26+
class SimpleTreeDecoder: public AbstractTreeDecoder {
27+
public:
28+
SimpleTreeDecoder(InStream &input);
29+
~SimpleTreeDecoder() override;
30+
31+
void readScanProps(
32+
TScanProps *pDst,
33+
const pt::ptree *root)
34+
override;
35+
36+
bool readNode(Defect *def) override;
37+
38+
private:
39+
struct Private;
40+
std::unique_ptr<Private> d;
41+
};
42+
43+
#endif /* H_GUARD_PARSER_JSON_SIMPLE_H */

0 commit comments

Comments
 (0)