summaryrefslogtreecommitdiff
path: root/upb/json/parser.h
blob: c693edf879739cda25ff8d56515775ef45bec76b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * upb - a minimalist implementation of protocol buffers.
 *
 * Copyright (c) 2014 Google Inc.  See LICENSE for details.
 * Author: Josh Haberman <jhaberman@gmail.com>
 *
 * upb::json::Parser can parse JSON according to a specific schema.
 * Support for parsing arbitrary JSON (schema-less) will be added later.
 */

#ifndef UPB_JSON_PARSER_H_
#define UPB_JSON_PARSER_H_

#include "upb/sink.h"

#ifdef __cplusplus
namespace upb {
namespace json {
class Parser;
}  // namespace json
}  // namespace upb
#endif

UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser);

// Internal-only struct used by the parser. A parser frame corresponds
// one-to-one with a handler (sink) frame.
typedef struct {
 UPB_PRIVATE_FOR_CPP
  upb_sink sink;
  // The current message in which we're parsing, and the field whose value we're
  // expecting next.
  const upb_msgdef *m;
  const upb_fielddef *f;

  // We are in a repeated-field context, ready to emit mapentries as
  // submessages. This flag alters the start-of-object (open-brace) behavior to
  // begin a sequence of mapentry messages rather than a single submessage.
  bool is_map;
  // We are in a map-entry message context. This flag is set when parsing the
  // value field of a single map entry and indicates to all value-field parsers
  // (subobjects, strings, numbers, and bools) that the map-entry submessage
  // should end as soon as the value is parsed.
  bool is_mapentry;
  // If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
  // message's map field that we're currently parsing. This differs from |f|
  // because |f| is the field in the *current* message (i.e., the map-entry
  // message itself), not the parent's field that leads to this map.
  const upb_fielddef *mapfield;
} upb_jsonparser_frame;


/* upb::json::Parser **********************************************************/

#define UPB_JSON_MAX_DEPTH 64

// Parses an incoming BytesStream, pushing the results to the destination sink.
UPB_DEFINE_CLASS0(upb::json::Parser,
 public:
  Parser(Status* status);
  ~Parser();

  // Resets the state of the printer, so that it will expect to begin a new
  // document.
  void Reset();

  // Resets the output pointer which will serve as our closure.  Implies
  // Reset().
  void ResetOutput(Sink* output);

  // The input to the printer.
  BytesSink* input();
,
UPB_DEFINE_STRUCT0(upb_json_parser,
  upb_byteshandler input_handler_;
  upb_bytessink input_;

  // Stack to track the JSON scopes we are in.
  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
  upb_jsonparser_frame *top;
  upb_jsonparser_frame *limit;

  upb_status *status;

  // Ragel's internal parsing stack for the parsing state machine.
  int current_state;
  int parser_stack[UPB_JSON_MAX_DEPTH];
  int parser_top;

  // The handle for the current buffer.
  const upb_bufhandle *handle;

  // Accumulate buffer.  See details in parser.rl.
  const char *accumulated;
  size_t accumulated_len;
  char *accumulate_buf;
  size_t accumulate_buf_size;

  // Multi-part text data.  See details in parser.rl.
  int multipart_state;
  upb_selector_t string_selector;

  // Input capture.  See details in parser.rl.
  const char *capture;

  // Intermediate result of parsing a unicode escape sequence.
  uint32_t digit;
));

UPB_BEGIN_EXTERN_C

void upb_json_parser_init(upb_json_parser *p, upb_status *status);
void upb_json_parser_uninit(upb_json_parser *p);
void upb_json_parser_reset(upb_json_parser *p);
void upb_json_parser_resetoutput(upb_json_parser *p, upb_sink *output);
upb_bytessink *upb_json_parser_input(upb_json_parser *p);

UPB_END_EXTERN_C

#ifdef __cplusplus

namespace upb {
namespace json {
inline Parser::Parser(Status* status) { upb_json_parser_init(this, status); }
inline Parser::~Parser() { upb_json_parser_uninit(this); }
inline void Parser::Reset() { upb_json_parser_reset(this); }
inline void Parser::ResetOutput(Sink* output) {
  upb_json_parser_resetoutput(this, output);
}
inline BytesSink* Parser::input() {
  return upb_json_parser_input(this);
}
}  // namespace json
}  // namespace upb

#endif


#endif  // UPB_JSON_PARSER_H_
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback