Flutter Engine
The Flutter Engine
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,
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.
162 g_autoptr(FlValue) owned_value = value;
163 FlValue* head = get_head();
164 if (head == nullptr) {
165 push(owned_value);
167 fl_value_append(head, owned_value);
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
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
bool Uint(unsigned i)
void push(FlValue *value)
bool EndArray(rapidjson::SizeType elementCount)
bool Int64(int64_t i)
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)
FlMessageCodec parent_instance
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63