Flutter Linux Embedder
fl_json_message_codec.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include <gmodule.h>
8 
9 #include <cstring>
10 
11 #include "rapidjson/reader.h"
12 #include "rapidjson/writer.h"
13 
14 G_DEFINE_QUARK(fl_json_message_codec_error_quark, fl_json_message_codec_error)
15 
17  FlMessageCodec parent_instance;
18 };
19 
20 G_DEFINE_TYPE(FlJsonMessageCodec,
21  fl_json_message_codec,
22  fl_message_codec_get_type())
23 
24 // Recursively writes #FlValue objects using rapidjson.
25 static gboolean write_value(rapidjson::Writer<rapidjson::StringBuffer>& writer,
26  FlValue* value,
27  GError** error) {
28  if (value == nullptr) {
29  writer.Null();
30  return TRUE;
31  }
32 
33  switch (fl_value_get_type(value)) {
34  case FL_VALUE_TYPE_NULL:
35  writer.Null();
36  break;
37  case FL_VALUE_TYPE_BOOL:
38  writer.Bool(fl_value_get_bool(value));
39  break;
40  case FL_VALUE_TYPE_INT:
41  writer.Int64(fl_value_get_int(value));
42  break;
44  writer.Double(fl_value_get_float(value));
45  break;
47  writer.String(fl_value_get_string(value));
48  break;
50  writer.StartArray();
51  const uint8_t* data = fl_value_get_uint8_list(value);
52  for (size_t i = 0; i < fl_value_get_length(value); i++) {
53  writer.Int(data[i]);
54  }
55  writer.EndArray();
56  break;
57  }
59  writer.StartArray();
60  const int32_t* data = fl_value_get_int32_list(value);
61  for (size_t i = 0; i < fl_value_get_length(value); i++) {
62  writer.Int(data[i]);
63  }
64  writer.EndArray();
65  break;
66  }
68  writer.StartArray();
69  const int64_t* data = fl_value_get_int64_list(value);
70  for (size_t i = 0; i < fl_value_get_length(value); i++) {
71  writer.Int64(data[i]);
72  }
73  writer.EndArray();
74  break;
75  }
77  writer.StartArray();
78  const double* data = fl_value_get_float_list(value);
79  for (size_t i = 0; i < fl_value_get_length(value); i++) {
80  writer.Double(data[i]);
81  }
82  writer.EndArray();
83  break;
84  }
85  case FL_VALUE_TYPE_LIST: {
86  writer.StartArray();
87  for (size_t i = 0; i < fl_value_get_length(value); i++) {
88  if (!write_value(writer, fl_value_get_list_value(value, i), error)) {
89  return FALSE;
90  }
91  }
92  writer.EndArray();
93  break;
94  }
95  case FL_VALUE_TYPE_MAP: {
96  writer.StartObject();
97  for (size_t i = 0; i < fl_value_get_length(value); i++) {
100  g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
102  "Invalid object key type");
103  return FALSE;
104  }
105  writer.Key(fl_value_get_string(key));
106  if (!write_value(writer, fl_value_get_map_value(value, i), error)) {
107  return FALSE;
108  }
109  }
110  writer.EndObject();
111  break;
112  }
113  default:
114  g_set_error(error, FL_MESSAGE_CODEC_ERROR,
116  "Unexpected FlValue type %d", fl_value_get_type(value));
117  return FALSE;
118  }
119 
120  return TRUE;
121 }
122 
123 // Handler to parse JSON using rapidjson in SAX mode.
125  GPtrArray* stack;
127  GError* error;
128 
130  stack = g_ptr_array_new_with_free_func(
131  reinterpret_cast<GDestroyNotify>(fl_value_unref));
132  key = nullptr;
133  error = nullptr;
134  }
135 
137  g_ptr_array_unref(stack);
138  if (key != nullptr) {
140  }
141  if (error != nullptr) {
142  g_error_free(error);
143  }
144  }
145 
146  // Gets the current head of the stack.
148  if (stack->len == 0) {
149  return nullptr;
150  }
151  return static_cast<FlValue*>(g_ptr_array_index(stack, stack->len - 1));
152  }
153 
154  // Pushes a value onto the stack.
155  void push(FlValue* value) { g_ptr_array_add(stack, fl_value_ref(value)); }
156 
157  // Pops the stack.
158  void pop() { g_ptr_array_remove_index(stack, stack->len - 1); }
159 
160  // Adds a new value to the stack.
161  bool add(FlValue* value) {
162  g_autoptr(FlValue) owned_value = value;
163  FlValue* head = get_head();
164  if (head == nullptr) {
165  push(owned_value);
166  } else if (fl_value_get_type(head) == FL_VALUE_TYPE_LIST) {
167  fl_value_append(head, owned_value);
168  } else if (fl_value_get_type(head) == FL_VALUE_TYPE_MAP) {
169  fl_value_set_take(head, key, fl_value_ref(owned_value));
170  key = nullptr;
171  } else {
173  "Can't add value to non container");
174  return false;
175  }
176 
177  if (fl_value_get_type(owned_value) == FL_VALUE_TYPE_LIST ||
178  fl_value_get_type(owned_value) == FL_VALUE_TYPE_MAP) {
179  push(value);
180  }
181 
182  return true;
183  }
184 
185  // The following implements the rapidjson SAX API.
186 
187  bool Null() { return add(fl_value_new_null()); }
188 
189  bool Bool(bool b) { return add(fl_value_new_bool(b)); }
190 
191  bool Int(int i) { return add(fl_value_new_int(i)); }
192 
193  bool Uint(unsigned i) { return add(fl_value_new_int(i)); }
194 
195  bool Int64(int64_t i) { return add(fl_value_new_int(i)); }
196 
197  bool Uint64(uint64_t i) {
198  // For some reason (bug in rapidjson?) this is not returned in Int64.
199  if (i == G_MAXINT64) {
200  return add(fl_value_new_int(i));
201  } else {
202  return add(fl_value_new_float(i));
203  }
204  }
205 
206  bool Double(double d) { return add(fl_value_new_float(d)); }
207 
208  bool RawNumber(const char* str, rapidjson::SizeType length, bool copy) {
210  "RawNumber not supported");
211  return false;
212  }
213 
214  bool String(const char* str, rapidjson::SizeType length, bool copy) {
216  return add(v);
217  }
218 
219  bool StartObject() { return add(fl_value_new_map()); }
220 
221  bool Key(const char* str, rapidjson::SizeType length, bool copy) {
222  if (key != nullptr) {
224  }
226  return true;
227  }
228 
229  bool EndObject(rapidjson::SizeType memberCount) {
230  pop();
231  return true;
232  }
233 
234  bool StartArray() { return add(fl_value_new_list()); }
235 
236  bool EndArray(rapidjson::SizeType elementCount) {
237  pop();
238  return true;
239  }
240 };
241 
242 // Implements FlMessageCodec:encode_message.
243 static GBytes* fl_json_message_codec_encode_message(FlMessageCodec* codec,
244  FlValue* message,
245  GError** error) {
246  rapidjson::StringBuffer buffer;
247  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
248 
249  if (!write_value(writer, message, error)) {
250  return nullptr;
251  }
252 
253  const gchar* text = buffer.GetString();
254  return g_bytes_new(text, strlen(text));
255 }
256 
257 // Implements FlMessageCodec:decode_message.
258 static FlValue* fl_json_message_codec_decode_message(FlMessageCodec* codec,
259  GBytes* message,
260  GError** error) {
261  gsize data_length;
262  const gchar* data =
263  static_cast<const char*>(g_bytes_get_data(message, &data_length));
264  if (!g_utf8_validate(data, data_length, nullptr)) {
265  g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
267  "Message is not valid UTF8");
268  return nullptr;
269  }
270 
271  FlValueHandler handler;
272  rapidjson::Reader reader;
273  rapidjson::MemoryStream ss(data, data_length);
274  if (!reader.Parse(ss, handler)) {
275  if (handler.error != nullptr) {
276  g_propagate_error(error, handler.error);
277  handler.error = nullptr;
278  } else {
279  g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
281  "Message is not valid JSON");
282  }
283  return nullptr;
284  }
285 
286  FlValue* value = handler.get_head();
287  if (value == nullptr) {
288  g_set_error(error, FL_JSON_MESSAGE_CODEC_ERROR,
290  "Message is not valid JSON");
291  return nullptr;
292  }
293 
294  return fl_value_ref(value);
295 }
296 
297 static void fl_json_message_codec_class_init(FlJsonMessageCodecClass* klass) {
298  FL_MESSAGE_CODEC_CLASS(klass)->encode_message =
300  FL_MESSAGE_CODEC_CLASS(klass)->decode_message =
302 }
303 
304 static void fl_json_message_codec_init(FlJsonMessageCodec* self) {}
305 
306 G_MODULE_EXPORT FlJsonMessageCodec* fl_json_message_codec_new() {
307  return static_cast<FlJsonMessageCodec*>(
308  g_object_new(fl_json_message_codec_get_type(), nullptr));
309 }
310 
311 G_MODULE_EXPORT gchar* fl_json_message_codec_encode(FlJsonMessageCodec* codec,
312  FlValue* value,
313  GError** error) {
314  g_return_val_if_fail(FL_IS_JSON_CODEC(codec), nullptr);
315 
316  rapidjson::StringBuffer buffer;
317  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
318 
319  if (!write_value(writer, value, error)) {
320  return nullptr;
321  }
322 
323  return g_strdup(buffer.GetString());
324 }
325 
326 G_MODULE_EXPORT FlValue* fl_json_message_codec_decode(FlJsonMessageCodec* codec,
327  const gchar* text,
328  GError** error) {
329  g_return_val_if_fail(FL_IS_JSON_CODEC(codec), nullptr);
330 
331  g_autoptr(GBytes) data = g_bytes_new_static(text, strlen(text));
333  FL_MESSAGE_CODEC(codec), data, error);
334  if (value == nullptr) {
335  return nullptr;
336  }
337 
338  return fl_value_ref(value);
339 }
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8
Definition: fl_json_message_codec.h:31
fl_value_get_int32_list
const G_MODULE_EXPORT int32_t * fl_value_get_int32_list(FlValue *self)
Definition: fl_value.cc:696
FL_VALUE_TYPE_UINT8_LIST
@ FL_VALUE_TYPE_UINT8_LIST
Definition: fl_value.h:70
fl_value_new_string_sized
G_MODULE_EXPORT FlValue * fl_value_new_string_sized(const gchar *value, size_t value_length)
Definition: fl_value.cc:283
FL_VALUE_TYPE_MAP
@ FL_VALUE_TYPE_MAP
Definition: fl_value.h:75
FlValueHandler::FlValueHandler
FlValueHandler()
Definition: fl_json_message_codec.cc:129
FlValueHandler::key
FlValue * key
Definition: fl_json_message_codec.cc:126
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE
Definition: fl_json_message_codec.h:33
FlValueHandler::String
bool String(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:214
FlValueHandler::StartObject
bool StartObject()
Definition: fl_json_message_codec.cc:219
fl_value_new_list
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:349
FlValueHandler::Uint64
bool Uint64(uint64_t i)
Definition: fl_json_message_codec.cc:197
fl_value_get_float_list
const G_MODULE_EXPORT double * fl_value_get_float_list(FlValue *self)
Definition: fl_value.cc:717
fl_value_new_bool
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:255
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_json_message_codec_new
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
Definition: fl_json_message_codec.cc:306
fl_json_message_codec.h
FlValueHandler::Bool
bool Bool(bool b)
Definition: fl_json_message_codec.cc:189
FlValueHandler::~FlValueHandler
~FlValueHandler()
Definition: fl_json_message_codec.cc:136
fl_value_set_take
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition: fl_value.cc:618
fl_value_new_null
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
FL_VALUE_TYPE_LIST
@ FL_VALUE_TYPE_LIST
Definition: fl_value.h:74
FlValueHandler::get_head
FlValue * get_head()
Definition: fl_json_message_codec.cc:147
_FlJsonMessageCodec
Definition: fl_json_message_codec.cc:16
fl_value_get_bool
G_MODULE_EXPORT bool fl_value_get_bool(FlValue *self)
Definition: fl_value.cc:661
fl_value_get_uint8_list
const G_MODULE_EXPORT uint8_t * fl_value_get_uint8_list(FlValue *self)
Definition: fl_value.cc:689
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
fl_value_get_string
const G_MODULE_EXPORT gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
FlValueHandler::EndArray
bool EndArray(rapidjson::SizeType elementCount)
Definition: fl_json_message_codec.cc:236
FlValueHandler::Key
bool Key(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:221
G_DEFINE_TYPE
G_DEFINE_TYPE(FlJsonMessageCodec, fl_json_message_codec, fl_message_codec_get_type()) static gboolean write_value(rapidjson
Definition: fl_json_message_codec.cc:20
FL_VALUE_TYPE_NULL
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:65
_FlJsonMessageCodec::parent_instance
FlMessageCodec parent_instance
Definition: fl_json_message_codec.cc:17
FlValueHandler::Uint
bool Uint(unsigned i)
Definition: fl_json_message_codec.cc:193
fl_value_get_int
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:668
fl_value_unref
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
Definition: fl_value.cc:400
FlValueHandler::add
bool add(FlValue *value)
Definition: fl_json_message_codec.cc:161
fl_value_ref
G_MODULE_EXPORT FlValue * fl_value_ref(FlValue *self)
Definition: fl_value.cc:394
G_DEFINE_QUARK
G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark, fl_binary_messenger_codec_error) G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
fl_value_get_list_value
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:776
fl_json_message_codec_class_init
static void fl_json_message_codec_class_init(FlJsonMessageCodecClass *klass)
Definition: fl_json_message_codec.cc:297
FlValueHandler::pop
void pop()
Definition: fl_json_message_codec.cc:158
fl_json_message_codec_encode
G_MODULE_EXPORT gchar * fl_json_message_codec_encode(FlJsonMessageCodec *codec, FlValue *value, GError **error)
Definition: fl_json_message_codec.cc:311
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:69
FlValueHandler::EndObject
bool EndObject(rapidjson::SizeType memberCount)
Definition: fl_json_message_codec.cc:229
FlValueHandler::RawNumber
bool RawNumber(const char *str, rapidjson::SizeType length, bool copy)
Definition: fl_json_message_codec.cc:208
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_json_message_codec_encode_message
static GBytes * fl_json_message_codec_encode_message(FlMessageCodec *codec, FlValue *message, GError **error)
Definition: fl_json_message_codec.cc:243
fl_json_message_codec_error_quark
G_MODULE_EXPORT GQuark fl_json_message_codec_error_quark(void) G_GNUC_CONST
FL_MESSAGE_CODEC_ERROR_FAILED
@ FL_MESSAGE_CODEC_ERROR_FAILED
Definition: fl_message_codec.h:34
fl_value_get_float
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition: fl_value.cc:675
fl_value_get_length
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:724
FL_VALUE_TYPE_INT64_LIST
@ FL_VALUE_TYPE_INT64_LIST
Definition: fl_value.h:72
FlValueHandler::push
void push(FlValue *value)
Definition: fl_json_message_codec.cc:155
FL_VALUE_TYPE_INT
@ FL_VALUE_TYPE_INT
Definition: fl_value.h:67
FlValueHandler::Int64
bool Int64(int64_t i)
Definition: fl_json_message_codec.cc:195
FlValueHandler::Double
bool Double(double d)
Definition: fl_json_message_codec.cc:206
fl_json_message_codec_decode_message
static FlValue * fl_json_message_codec_decode_message(FlMessageCodec *codec, GBytes *message, GError **error)
Definition: fl_json_message_codec.cc:258
FlValueHandler::Null
bool Null()
Definition: fl_json_message_codec.cc:187
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
FlValueHandler
Definition: fl_json_message_codec.cc:124
FL_VALUE_TYPE_FLOAT_LIST
@ FL_VALUE_TYPE_FLOAT_LIST
Definition: fl_value.h:73
FL_JSON_MESSAGE_CODEC_ERROR
#define FL_JSON_MESSAGE_CODEC_ERROR
Definition: fl_json_message_codec.h:27
fl_json_message_codec_decode
G_MODULE_EXPORT FlValue * fl_json_message_codec_decode(FlJsonMessageCodec *codec, const gchar *text, GError **error)
Definition: fl_json_message_codec.cc:326
fl_value_append
G_MODULE_EXPORT void fl_value_append(FlValue *self, FlValue *value)
Definition: fl_value.cc:592
buffer
static const uint8_t buffer[]
Definition: fl_pixel_buffer_texture_test.cc:44
FL_VALUE_TYPE_FLOAT
@ FL_VALUE_TYPE_FLOAT
Definition: fl_value.h:68
FL_VALUE_TYPE_INT32_LIST
@ FL_VALUE_TYPE_INT32_LIST
Definition: fl_value.h:71
FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE
@ FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE
Definition: fl_message_codec.h:37
FlValueHandler::error
GError * error
Definition: fl_json_message_codec.cc:127
fl_value_new_float
G_MODULE_EXPORT FlValue * fl_value_new_float(double value)
Definition: fl_value.cc:269
FlValueHandler::Int
bool Int(int i)
Definition: fl_json_message_codec.cc:191
FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
Definition: fl_json_message_codec.h:32
fl_value_get_map_key
G_MODULE_EXPORT FlValue * fl_value_get_map_key(FlValue *self, size_t index)
Definition: fl_value.cc:784
fl_value_get_int64_list
const G_MODULE_EXPORT int64_t * fl_value_get_int64_list(FlValue *self)
Definition: fl_value.cc:703
FL_VALUE_TYPE_BOOL
@ FL_VALUE_TYPE_BOOL
Definition: fl_value.h:66
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
length
size_t length
Definition: fl_standard_message_codec_test.cc:1113
fl_json_message_codec_init
static void fl_json_message_codec_init(FlJsonMessageCodec *self)
Definition: fl_json_message_codec.cc:304
fl_value_get_map_value
G_MODULE_EXPORT FlValue * fl_value_get_map_value(FlValue *self, size_t index)
Definition: fl_value.cc:792
FlValueHandler::StartArray
bool StartArray()
Definition: fl_json_message_codec.cc:234
FlValueHandler::stack
GPtrArray * stack
Definition: fl_json_message_codec.cc:125
FL_MESSAGE_CODEC_ERROR
#define FL_MESSAGE_CODEC_ERROR
Definition: fl_message_codec.h:30