This is Unofficial EPICS BASE Doxygen Site
parsehelper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
6 #include <stdexcept>
7 #include <sstream>
8 
9 #define epicsExportSharedSymbols
10 #include <pv/pvdVersion.h>
11 
12 #include "pv/json.h"
13 
14 namespace {
15 
16 void check_trailing(const std::string& line)
17 {
18  size_t idx = line.find_first_not_of(" \t\n\r");
19  if(idx==line.npos) return;
20  // TODO: detect the end of potentially multi-line comments...
21  // for now trailing comments not allowed
22  throw std::runtime_error("Trailing junk");
23 }
24 
25 } // namespace
26 
27 namespace epics{namespace pvData{
28 
29 bool yajl_parse_helper(std::istream& src,
30  yajl_handle handle)
31 {
32  unsigned linenum=0;
33 #ifndef EPICS_YAJL_VERSION
34  bool done = false;
35 #endif
36 
37  std::string line;
38  while(std::getline(src, line)) {
39  linenum++;
40 
41 #ifndef EPICS_YAJL_VERSION
42  if(done) {
43  check_trailing(line);
44  continue;
45  }
46 #endif
47 
48  yajl_status sts = yajl_parse(handle, (const unsigned char*)line.c_str(), line.size());
49 
50  switch(sts) {
51  case yajl_status_ok: {
52  size_t consumed = yajl_get_bytes_consumed(handle);
53 
54  if(consumed<line.size()) {
55  check_trailing(line.substr(consumed));
56  }
57 
58 #ifndef EPICS_YAJL_VERSION
59  done = true;
60 #endif
61  break;
62  }
64  return false;
65 #ifndef EPICS_YAJL_VERSION
66  case yajl_status_insufficient_data:
67  // continue with next line
68  break;
69 #endif
70  case yajl_status_error:
71  {
72  std::ostringstream msg;
73  unsigned char *raw = yajl_get_error(handle, 1, (const unsigned char*)line.c_str(), line.size());
74  if(!raw) {
75  msg<<"Unknown error on line "<<linenum;
76  } else {
77  try {
78  msg<<"Error on line "<<linenum<<" : "<<(const char*)raw;
79  }catch(...){
80  yajl_free_error(handle, raw);
81  throw;
82  }
83  yajl_free_error(handle, raw);
84  }
85  throw std::runtime_error(msg.str());
86  }
87  }
88  }
89 
90  if(!src.eof() || src.bad()) {
91  std::ostringstream msg;
92  msg<<"I/O error after line "<<linenum;
93  throw std::runtime_error(msg.str());
94 
95 #ifndef EPICS_YAJL_VERSION
96  } else if(!done) {
97  switch(yajl_parse_complete(handle)) {
98 #else
99  } else {
100  switch(yajl_complete_parse(handle)) {
101 #endif
102  case yajl_status_ok:
103  break;
105  return false;
106 #ifndef EPICS_YAJL_VERSION
107  case yajl_status_insufficient_data:
108  throw std::runtime_error("unexpected end of input");
109 #endif
110  case yajl_status_error:
111  throw std::runtime_error("Error while completing parsing");
112  }
113  }
114 
115  return true;
116 }
117 
118 }} // namespace epics::pvData
unsigned char * yajl_get_error(yajl_handle hand, int verbose, const unsigned char *jsonText, size_t jsonTextLen)
Definition: yajl.c:160
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
int linenum
Definition: flex.c:71
char * line
Definition: reader.c:25
void yajl_free_error(yajl_handle hand, unsigned char *str)
Definition: yajl.c:175
yajl_status
Definition: yajl_parse.h:32
yajl_status yajl_parse(yajl_handle hand, const unsigned char *jsonText, size_t jsonTextLen)
Definition: yajl.c:121
void done(int k)
Definition: antelope.c:77
bool yajl_parse_helper(std::istream &src, yajl_handle handle)
Definition: parsehelper.cpp:29
yajl_status yajl_complete_parse(yajl_handle hand)
Definition: yajl.c:142
size_t yajl_get_bytes_consumed(yajl_handle hand)
Definition: yajl.c:167