Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
5#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
6
7#include <gmodule.h>
8
9#include <cstring>
10
11#include "rapidjson/reader.h"
12#include "rapidjson/writer.h"
13
14G_DEFINE_QUARK(fl_json_message_codec_error_quark, fl_json_message_codec_error)
15
17 FlMessageCodec parent_instance;
18};
19
20G_DEFINE_TYPE(FlJsonMessageCodec,
21 fl_json_message_codec,
22 fl_message_codec_get_type())
23
24// Recursively writes #FlValue objects using rapidjson.
25static 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)) {
35 writer.Null();
36 break;
38 writer.Bool(fl_value_get_bool(value));
39 break;
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++) {
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.
243static GBytes* fl_json_message_codec_encode_message(FlMessageCodec* codec,
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.
258static 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)) {
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 {
281 "Message is not valid JSON");
282 }
283 return nullptr;
284 }
285
286 FlValue* value = handler.get_head();
287 if (value == nullptr) {
290 "Message is not valid JSON");
291 return nullptr;
292 }
293
294 return fl_value_ref(value);
295}
296
297static 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
304static void fl_json_message_codec_init(FlJsonMessageCodec* self) {}
305
306G_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
311G_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
326G_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}
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark, fl_binary_messenger_codec_error) G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl
G_DEFINE_TYPE(FlJsonMessageCodec, fl_json_message_codec, fl_message_codec_get_type()) static gboolean write_value(rapidjson
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
static GBytes * fl_json_message_codec_encode_message(FlMessageCodec *codec, FlValue *message, GError **error)
G_MODULE_EXPORT gchar * fl_json_message_codec_encode(FlJsonMessageCodec *codec, FlValue *value, GError **error)
static void fl_json_message_codec_init(FlJsonMessageCodec *self)
static FlValue * fl_json_message_codec_decode_message(FlMessageCodec *codec, GBytes *message, GError **error)
static void fl_json_message_codec_class_init(FlJsonMessageCodecClass *klass)
G_MODULE_EXPORT FlValue * fl_json_message_codec_decode(FlJsonMessageCodec *codec, const gchar *text, GError **error)
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_OBJECT_KEY_TYPE
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_UTF8
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
G_MODULE_EXPORT GQuark fl_json_message_codec_error_quark(void) G_GNUC_CONST
#define FL_JSON_MESSAGE_CODEC_ERROR
@ FL_MESSAGE_CODEC_ERROR_UNSUPPORTED_TYPE
@ FL_MESSAGE_CODEC_ERROR_FAILED
#define FL_MESSAGE_CODEC_ERROR
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition fl_value.cc:366
G_MODULE_EXPORT FlValue * fl_value_ref(FlValue *self)
Definition fl_value.cc:394
G_MODULE_EXPORT const double * fl_value_get_float_list(FlValue *self)
Definition fl_value.cc:717
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition fl_value.cc:668
G_MODULE_EXPORT void fl_value_unref(FlValue *self)
Definition fl_value.cc:400
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition fl_value.cc:466
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition fl_value.cc:251
G_MODULE_EXPORT void fl_value_append(FlValue *self, FlValue *value)
Definition fl_value.cc:592
G_MODULE_EXPORT FlValue * fl_value_get_map_key(FlValue *self, size_t index)
Definition fl_value.cc:784
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition fl_value.cc:255
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition fl_value.cc:618
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition fl_value.cc:682
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition fl_value.cc:262
G_MODULE_EXPORT FlValue * fl_value_new_float(double value)
Definition fl_value.cc:269
G_MODULE_EXPORT const uint8_t * fl_value_get_uint8_list(FlValue *self)
Definition fl_value.cc:689
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition fl_value.cc:776
G_MODULE_EXPORT bool fl_value_get_bool(FlValue *self)
Definition fl_value.cc:661
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition fl_value.cc:349
G_MODULE_EXPORT FlValue * fl_value_new_string_sized(const gchar *value, size_t value_length)
Definition fl_value.cc:283
G_MODULE_EXPORT FlValue * fl_value_get_map_value(FlValue *self, size_t index)
Definition fl_value.cc:792
G_MODULE_EXPORT double fl_value_get_float(FlValue *self)
Definition fl_value.cc:675
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition fl_value.cc:724
G_MODULE_EXPORT const int32_t * fl_value_get_int32_list(FlValue *self)
Definition fl_value.cc:696
G_MODULE_EXPORT const int64_t * fl_value_get_int64_list(FlValue *self)
Definition fl_value.cc:703
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition fl_value.h:69
@ FL_VALUE_TYPE_NULL
Definition fl_value.h:65
@ FL_VALUE_TYPE_INT
Definition fl_value.h:67
@ FL_VALUE_TYPE_BOOL
Definition fl_value.h:66
@ FL_VALUE_TYPE_INT32_LIST
Definition fl_value.h:71
@ FL_VALUE_TYPE_UINT8_LIST
Definition fl_value.h:70
@ FL_VALUE_TYPE_LIST
Definition fl_value.h:74
@ FL_VALUE_TYPE_MAP
Definition fl_value.h:75
@ FL_VALUE_TYPE_INT64_LIST
Definition fl_value.h:72
@ FL_VALUE_TYPE_FLOAT_LIST
Definition fl_value.h:73
@ FL_VALUE_TYPE_FLOAT
Definition fl_value.h:68
size_t length
std::u16string text
Win32Message message
return FALSE
Definition copy.py:1
bool Uint(unsigned i)
void push(FlValue *value)
bool EndArray(rapidjson::SizeType elementCount)
bool RawNumber(const char *str, rapidjson::SizeType length, bool copy)
bool String(const char *str, rapidjson::SizeType length, bool copy)
bool add(FlValue *value)
bool Uint64(uint64_t i)
bool EndObject(rapidjson::SizeType memberCount)
bool Key(const char *str, rapidjson::SizeType length, bool copy)