mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
AK: JsonParser improvements
- Parsing invalid JSON no longer asserts Instead of asserting when coming across malformed JSON, JsonParser::parse now returns an Optional<JsonValue>. - Disallow trailing commas in JSON objects and arrays - No longer parse 'undefined', as that is a purely JS thing - No longer allow non-whitespace after anything consumed by the initial parse() call. Examples of things that were valid and no longer are: - undefineddfz - {"foo": 1}abcd - [1,2,3]4 - JsonObject.for_each_member now iterates in original insertion order
This commit is contained in:
parent
39576b2238
commit
e8e728454c
Notes:
sideshowbarker
2024-07-19 05:40:46 +09:00
Author: https://github.com/mattco98 Commit: https://github.com/SerenityOS/serenity/commit/e8e728454c5 Pull-request: https://github.com/SerenityOS/serenity/pull/2545 Reviewed-by: https://github.com/Dexesttp Reviewed-by: https://github.com/awesomekling
29 changed files with 189 additions and 118 deletions
|
@ -41,26 +41,32 @@ public:
|
||||||
~JsonObject() {}
|
~JsonObject() {}
|
||||||
|
|
||||||
JsonObject(const JsonObject& other)
|
JsonObject(const JsonObject& other)
|
||||||
: m_members(other.m_members)
|
: m_order(other.m_order)
|
||||||
|
, m_members(other.m_members)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject(JsonObject&& other)
|
JsonObject(JsonObject&& other)
|
||||||
: m_members(move(other.m_members))
|
: m_order(move(other.m_order))
|
||||||
|
, m_members(move(other.m_members))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject& operator=(const JsonObject& other)
|
JsonObject& operator=(const JsonObject& other)
|
||||||
{
|
{
|
||||||
if (this != &other)
|
if (this != &other) {
|
||||||
m_members = other.m_members;
|
m_members = other.m_members;
|
||||||
|
m_order = other.m_order;
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject& operator=(JsonObject&& other)
|
JsonObject& operator=(JsonObject&& other)
|
||||||
{
|
{
|
||||||
if (this != &other)
|
if (this != &other) {
|
||||||
m_members = move(other.m_members);
|
m_members = move(other.m_members);
|
||||||
|
m_order = move(other.m_order);
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +76,7 @@ public:
|
||||||
JsonValue get(const String& key) const
|
JsonValue get(const String& key) const
|
||||||
{
|
{
|
||||||
auto* value = get_ptr(key);
|
auto* value = get_ptr(key);
|
||||||
return value ? *value : JsonValue(JsonValue::Type::Undefined);
|
return value ? *value : JsonValue(JsonValue::Type::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue get_or(const String& key, JsonValue alternative) const
|
JsonValue get_or(const String& key, JsonValue alternative) const
|
||||||
|
@ -94,14 +100,17 @@ public:
|
||||||
|
|
||||||
void set(const String& key, JsonValue value)
|
void set(const String& key, JsonValue value)
|
||||||
{
|
{
|
||||||
|
m_order.append(key);
|
||||||
m_members.set(key, move(value));
|
m_members.set(key, move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void for_each_member(Callback callback) const
|
void for_each_member(Callback callback) const
|
||||||
{
|
{
|
||||||
for (auto& it : m_members)
|
for (size_t i = 0; i < m_order.size(); ++i) {
|
||||||
callback(it.key, it.value);
|
auto property = m_order[i];
|
||||||
|
callback(property, m_members.get(property).value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Builder>
|
template<typename Builder>
|
||||||
|
@ -113,6 +122,7 @@ public:
|
||||||
String to_string() const { return serialized<StringBuilder>(); }
|
String to_string() const { return serialized<StringBuilder>(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Vector<String> m_order;
|
||||||
HashMap<String, JsonValue> m_members;
|
HashMap<String, JsonValue> m_members;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,9 +203,6 @@ inline void JsonValue::serialize(Builder& builder) const
|
||||||
case Type::UnsignedInt64:
|
case Type::UnsignedInt64:
|
||||||
builder.appendf("%llu", as_u64());
|
builder.appendf("%llu", as_u64());
|
||||||
break;
|
break;
|
||||||
case Type::Undefined:
|
|
||||||
builder.append("undefined");
|
|
||||||
break;
|
|
||||||
case Type::Null:
|
case Type::Null:
|
||||||
builder.append("null");
|
builder.append("null");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -62,15 +62,16 @@ void JsonParser::consume_whitespace()
|
||||||
consume_while([](char ch) { return is_whitespace(ch); });
|
consume_while([](char ch) { return is_whitespace(ch); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonParser::consume_specific(char expected_ch)
|
bool JsonParser::consume_specific(char expected_ch)
|
||||||
{
|
{
|
||||||
char consumed_ch = consume();
|
char consumed_ch = consume();
|
||||||
ASSERT(consumed_ch == expected_ch);
|
return consumed_ch == expected_ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
String JsonParser::consume_quoted_string()
|
String JsonParser::consume_quoted_string()
|
||||||
{
|
{
|
||||||
consume_specific('"');
|
if (!consume_specific('"'))
|
||||||
|
return {};
|
||||||
Vector<char, 1024> buffer;
|
Vector<char, 1024> buffer;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -136,7 +137,8 @@ String JsonParser::consume_quoted_string()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consume_specific('"');
|
if (!consume_specific('"'))
|
||||||
|
return {};
|
||||||
|
|
||||||
if (buffer.is_empty())
|
if (buffer.is_empty())
|
||||||
return String::empty();
|
return String::empty();
|
||||||
|
@ -151,55 +153,78 @@ String JsonParser::consume_quoted_string()
|
||||||
return last_string_starting_with_character;
|
return last_string_starting_with_character;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject JsonParser::parse_object()
|
Optional<JsonValue> JsonParser::parse_object()
|
||||||
{
|
{
|
||||||
JsonObject object;
|
JsonObject object;
|
||||||
consume_specific('{');
|
if (!consume_specific('{'))
|
||||||
|
return {};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
if (peek() == '}')
|
if (peek() == '}')
|
||||||
break;
|
break;
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
auto name = consume_quoted_string();
|
auto name = consume_quoted_string();
|
||||||
|
if (name.is_null())
|
||||||
|
return {};
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
consume_specific(':');
|
if (!consume_specific(':'))
|
||||||
|
return {};
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
auto value = parse();
|
auto value = parse_helper();
|
||||||
object.set(name, move(value));
|
if (!value.has_value())
|
||||||
|
return {};
|
||||||
|
object.set(name, move(value.value()));
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
if (peek() == '}')
|
if (peek() == '}')
|
||||||
break;
|
break;
|
||||||
consume_specific(',');
|
if (!consume_specific(','))
|
||||||
|
return {};
|
||||||
|
consume_whitespace();
|
||||||
|
if (peek() == '}')
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
consume_specific('}');
|
if (!consume_specific('}'))
|
||||||
|
return {};
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray JsonParser::parse_array()
|
Optional<JsonValue> JsonParser::parse_array()
|
||||||
{
|
{
|
||||||
JsonArray array;
|
JsonArray array;
|
||||||
consume_specific('[');
|
if (!consume_specific('['))
|
||||||
|
return {};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
if (peek() == ']')
|
if (peek() == ']')
|
||||||
break;
|
break;
|
||||||
array.append(parse());
|
auto element = parse_helper();
|
||||||
|
if (!element.has_value())
|
||||||
|
return {};
|
||||||
|
array.append(element.value());
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
if (peek() == ']')
|
if (peek() == ']')
|
||||||
break;
|
break;
|
||||||
consume_specific(',');
|
if (!consume_specific(','))
|
||||||
|
return {};
|
||||||
|
consume_whitespace();
|
||||||
|
if (peek() == ']')
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
consume_specific(']');
|
if (!consume_specific(']'))
|
||||||
|
return {};
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_string()
|
Optional<JsonValue> JsonParser::parse_string()
|
||||||
{
|
{
|
||||||
return consume_quoted_string();
|
auto result = consume_quoted_string();
|
||||||
|
if (result.is_null())
|
||||||
|
return {};
|
||||||
|
return JsonValue(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_number()
|
Optional<JsonValue> JsonParser::parse_number()
|
||||||
{
|
{
|
||||||
JsonValue value;
|
JsonValue value;
|
||||||
Vector<char, 128> number_buffer;
|
Vector<char, 128> number_buffer;
|
||||||
|
@ -235,7 +260,10 @@ JsonValue JsonParser::parse_number()
|
||||||
if (to_signed_result.has_value()) {
|
if (to_signed_result.has_value()) {
|
||||||
whole = to_signed_result.value();
|
whole = to_signed_result.value();
|
||||||
} else {
|
} else {
|
||||||
whole = number_string.to_int().value();
|
auto number = number_string.to_int();
|
||||||
|
if (!number.has_value())
|
||||||
|
return {};
|
||||||
|
whole = number.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int fraction = fraction_string.to_uint().value();
|
int fraction = fraction_string.to_uint().value();
|
||||||
|
@ -252,7 +280,10 @@ JsonValue JsonParser::parse_number()
|
||||||
if (to_unsigned_result.has_value()) {
|
if (to_unsigned_result.has_value()) {
|
||||||
value = JsonValue(to_unsigned_result.value());
|
value = JsonValue(to_unsigned_result.value());
|
||||||
} else {
|
} else {
|
||||||
value = JsonValue(number_string.to_int().value());
|
auto number = number_string.to_int();
|
||||||
|
if (!number.has_value())
|
||||||
|
return {};
|
||||||
|
value = JsonValue(number.value());
|
||||||
}
|
}
|
||||||
#ifndef KERNEL
|
#ifndef KERNEL
|
||||||
}
|
}
|
||||||
|
@ -261,37 +292,37 @@ JsonValue JsonParser::parse_number()
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JsonParser::consume_string(const char* str)
|
bool JsonParser::consume_string(const char* str)
|
||||||
{
|
{
|
||||||
for (size_t i = 0, length = strlen(str); i < length; ++i)
|
for (size_t i = 0, length = strlen(str); i < length; ++i) {
|
||||||
consume_specific(str[i]);
|
if (!consume_specific(str[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_true()
|
Optional<JsonValue> JsonParser::parse_true()
|
||||||
{
|
{
|
||||||
consume_string("true");
|
if (!consume_string("true"))
|
||||||
|
return {};
|
||||||
return JsonValue(true);
|
return JsonValue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_false()
|
Optional<JsonValue> JsonParser::parse_false()
|
||||||
{
|
{
|
||||||
consume_string("false");
|
if (!consume_string("false"))
|
||||||
|
return {};
|
||||||
return JsonValue(false);
|
return JsonValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_null()
|
Optional<JsonValue> JsonParser::parse_null()
|
||||||
{
|
{
|
||||||
consume_string("null");
|
if (!consume_string("null"))
|
||||||
|
return {};
|
||||||
return JsonValue(JsonValue::Type::Null);
|
return JsonValue(JsonValue::Type::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonParser::parse_undefined()
|
Optional<JsonValue> JsonParser::parse_helper()
|
||||||
{
|
|
||||||
consume_string("undefined");
|
|
||||||
return JsonValue(JsonValue::Type::Undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue JsonParser::parse()
|
|
||||||
{
|
{
|
||||||
consume_whitespace();
|
consume_whitespace();
|
||||||
auto type_hint = peek();
|
auto type_hint = peek();
|
||||||
|
@ -320,10 +351,19 @@ JsonValue JsonParser::parse()
|
||||||
return parse_true();
|
return parse_true();
|
||||||
case 'n':
|
case 'n':
|
||||||
return parse_null();
|
return parse_null();
|
||||||
case 'u':
|
|
||||||
return parse_undefined();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonValue();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<JsonValue> JsonParser::parse() {
|
||||||
|
auto result = parse_helper();
|
||||||
|
if (!result.has_value())
|
||||||
|
return {};
|
||||||
|
consume_whitespace();
|
||||||
|
if (m_index != m_input.length())
|
||||||
|
return {};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,23 +40,24 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue parse();
|
Optional<JsonValue> parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Optional<JsonValue> parse_helper();
|
||||||
|
|
||||||
char peek() const;
|
char peek() const;
|
||||||
char consume();
|
char consume();
|
||||||
void consume_whitespace();
|
void consume_whitespace();
|
||||||
void consume_specific(char expected_ch);
|
bool consume_specific(char expected_ch);
|
||||||
void consume_string(const char*);
|
bool consume_string(const char*);
|
||||||
String consume_quoted_string();
|
String consume_quoted_string();
|
||||||
JsonArray parse_array();
|
Optional<JsonValue> parse_array();
|
||||||
JsonObject parse_object();
|
Optional<JsonValue> parse_object();
|
||||||
JsonValue parse_number();
|
Optional<JsonValue> parse_number();
|
||||||
JsonValue parse_string();
|
Optional<JsonValue> parse_string();
|
||||||
JsonValue parse_false();
|
Optional<JsonValue> parse_false();
|
||||||
JsonValue parse_true();
|
Optional<JsonValue> parse_true();
|
||||||
JsonValue parse_null();
|
Optional<JsonValue> parse_null();
|
||||||
JsonValue parse_undefined();
|
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
void consume_while(C);
|
void consume_while(C);
|
||||||
|
|
|
@ -75,7 +75,7 @@ void JsonValue::copy_from(const JsonValue& other)
|
||||||
|
|
||||||
JsonValue::JsonValue(JsonValue&& other)
|
JsonValue::JsonValue(JsonValue&& other)
|
||||||
{
|
{
|
||||||
m_type = exchange(other.m_type, Type::Undefined);
|
m_type = exchange(other.m_type, Type::Null);
|
||||||
m_value.as_string = exchange(other.m_value.as_string, nullptr);
|
m_value.as_string = exchange(other.m_value.as_string, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ JsonValue& JsonValue::operator=(JsonValue&& other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
clear();
|
clear();
|
||||||
m_type = exchange(other.m_type, Type::Undefined);
|
m_type = exchange(other.m_type, Type::Null);
|
||||||
m_value.as_string = exchange(other.m_value.as_string, nullptr);
|
m_value.as_string = exchange(other.m_value.as_string, nullptr);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -247,11 +247,11 @@ void JsonValue::clear()
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m_type = Type::Undefined;
|
m_type = Type::Null;
|
||||||
m_value.as_string = nullptr;
|
m_value.as_string = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonValue JsonValue::from_string(const StringView& input)
|
Optional<JsonValue> JsonValue::from_string(const StringView& input)
|
||||||
{
|
{
|
||||||
return JsonParser(input).parse();
|
return JsonParser(input).parse();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ namespace AK {
|
||||||
class JsonValue {
|
class JsonValue {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Undefined,
|
|
||||||
Null,
|
Null,
|
||||||
Int32,
|
Int32,
|
||||||
UnsignedInt32,
|
UnsignedInt32,
|
||||||
|
@ -52,7 +51,7 @@ public:
|
||||||
Object,
|
Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
static JsonValue from_string(const StringView&);
|
static Optional<JsonValue> from_string(const StringView&);
|
||||||
|
|
||||||
explicit JsonValue(Type = Type::Null);
|
explicit JsonValue(Type = Type::Null);
|
||||||
~JsonValue() { clear(); }
|
~JsonValue() { clear(); }
|
||||||
|
@ -188,7 +187,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const { return m_type == Type::Null; }
|
bool is_null() const { return m_type == Type::Null; }
|
||||||
bool is_undefined() const { return m_type == Type::Undefined; }
|
|
||||||
bool is_bool() const { return m_type == Type::Bool; }
|
bool is_bool() const { return m_type == Type::Bool; }
|
||||||
bool is_string() const { return m_type == Type::String; }
|
bool is_string() const { return m_type == Type::String; }
|
||||||
bool is_i32() const { return m_type == Type::Int32; }
|
bool is_i32() const { return m_type == Type::Int32; }
|
||||||
|
@ -246,7 +244,7 @@ private:
|
||||||
void clear();
|
void clear();
|
||||||
void copy_from(const JsonValue&);
|
void copy_from(const JsonValue&);
|
||||||
|
|
||||||
Type m_type { Type::Undefined };
|
Type m_type { Type::Null };
|
||||||
|
|
||||||
union {
|
union {
|
||||||
StringImpl* as_string { nullptr };
|
StringImpl* as_string { nullptr };
|
||||||
|
|
|
@ -48,7 +48,7 @@ TEST_CASE(load_form)
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
JsonValue form_json = JsonValue::from_string(builder.to_string());
|
JsonValue form_json = JsonValue::from_string(builder.to_string()).value();
|
||||||
|
|
||||||
EXPECT(form_json.is_object());
|
EXPECT(form_json.is_object());
|
||||||
|
|
||||||
|
@ -87,14 +87,14 @@ BENCHMARK_CASE(load_4chan_catalog)
|
||||||
auto json_string = builder.to_string();
|
auto json_string = builder.to_string();
|
||||||
|
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
JsonValue form_json = JsonValue::from_string(json_string);
|
JsonValue form_json = JsonValue::from_string(json_string).value();
|
||||||
EXPECT(form_json.is_array());
|
EXPECT(form_json.is_array());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(json_empty_string)
|
TEST_CASE(json_empty_string)
|
||||||
{
|
{
|
||||||
auto json = JsonValue::from_string("\"\"");
|
auto json = JsonValue::from_string("\"\"").value();
|
||||||
EXPECT_EQ(json.type(), JsonValue::Type::String);
|
EXPECT_EQ(json.type(), JsonValue::Type::String);
|
||||||
EXPECT_EQ(json.as_string().is_null(), false);
|
EXPECT_EQ(json.as_string().is_null(), false);
|
||||||
EXPECT_EQ(json.as_string().is_empty(), true);
|
EXPECT_EQ(json.as_string().is_empty(), true);
|
||||||
|
@ -102,7 +102,7 @@ TEST_CASE(json_empty_string)
|
||||||
|
|
||||||
TEST_CASE(json_utf8_character)
|
TEST_CASE(json_utf8_character)
|
||||||
{
|
{
|
||||||
auto json = JsonValue::from_string("\"\xc3\x84\"");
|
auto json = JsonValue::from_string("\"\xc3\x84\"").value();
|
||||||
EXPECT_EQ(json.type(), JsonValue::Type::String);
|
EXPECT_EQ(json.type(), JsonValue::Type::String);
|
||||||
EXPECT_EQ(json.as_string().is_null(), false);
|
EXPECT_EQ(json.as_string().is_null(), false);
|
||||||
EXPECT_EQ(json.as_string().length(), size_t { 2 });
|
EXPECT_EQ(json.as_string().length(), size_t { 2 });
|
||||||
|
|
|
@ -127,10 +127,11 @@ void DevicesModel::update()
|
||||||
if (!proc_devices->open(Core::IODevice::OpenMode::ReadOnly))
|
if (!proc_devices->open(Core::IODevice::OpenMode::ReadOnly))
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
auto json = JsonValue::from_string(proc_devices->read_all()).as_array();
|
auto json = JsonValue::from_string(proc_devices->read_all());
|
||||||
|
ASSERT(json.has_value());
|
||||||
|
|
||||||
m_devices.clear();
|
m_devices.clear();
|
||||||
json.for_each([this](auto& value) {
|
json.value().as_array().for_each([this](auto& value) {
|
||||||
JsonObject device = value.as_object();
|
JsonObject device = value.as_object();
|
||||||
DeviceInfo device_info;
|
DeviceInfo device_info;
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,9 @@ void MemoryStatsWidget::refresh()
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
auto file_contents = proc_memstat->read_all();
|
auto file_contents = proc_memstat->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_object();
|
auto json_result = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json_result.has_value());
|
||||||
|
auto json = json_result.value().as_object();
|
||||||
|
|
||||||
unsigned kmalloc_eternal_allocated = json.get("kmalloc_eternal_allocated").to_u32();
|
unsigned kmalloc_eternal_allocated = json.get("kmalloc_eternal_allocated").to_u32();
|
||||||
(void)kmalloc_eternal_allocated;
|
(void)kmalloc_eternal_allocated;
|
||||||
|
|
|
@ -46,7 +46,9 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents);
|
auto json_result = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json_result.has_value());
|
||||||
|
auto json = json_result.value();
|
||||||
|
|
||||||
if (!json.is_object()) {
|
if (!json.is_object()) {
|
||||||
fprintf(stderr, "Malformed input\n");
|
fprintf(stderr, "Malformed input\n");
|
||||||
|
|
|
@ -167,11 +167,12 @@ void RemoteProcess::update()
|
||||||
dbg() << "Got data size " << length << " and read that many bytes";
|
dbg() << "Got data size " << length << " and read that many bytes";
|
||||||
|
|
||||||
auto json_value = JsonValue::from_string(data);
|
auto json_value = JsonValue::from_string(data);
|
||||||
ASSERT(json_value.is_object());
|
ASSERT(json_value.has_value());
|
||||||
|
ASSERT(json_value.value().is_object());
|
||||||
|
|
||||||
dbg() << "Got JSON response " << json_value.to_string();
|
dbg() << "Got JSON response " << json_value.value().to_string();
|
||||||
|
|
||||||
auto& response = json_value.as_object();
|
auto& response = json_value.value().as_object();
|
||||||
|
|
||||||
auto response_type = response.get("type").as_string_or({});
|
auto response_type = response.get("type").as_string_or({});
|
||||||
if (response_type.is_null())
|
if (response_type.is_null())
|
||||||
|
|
|
@ -172,12 +172,13 @@ OwnPtr<Profile> Profile::load_from_perfcore_file(const StringView& path)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto json = JsonValue::from_string(file->read_all());
|
auto json = JsonValue::from_string(file->read_all());
|
||||||
if (!json.is_object()) {
|
ASSERT(json.has_value());
|
||||||
|
if (!json.value().is_object()) {
|
||||||
fprintf(stderr, "Invalid perfcore format (not a JSON object)\n");
|
fprintf(stderr, "Invalid perfcore format (not a JSON object)\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& object = json.as_object();
|
auto& object = json.value().as_object();
|
||||||
auto executable_path = object.get("executable").to_string();
|
auto executable_path = object.get("executable").to_string();
|
||||||
|
|
||||||
MappedFile elf_file(executable_path);
|
MappedFile elf_file(executable_path);
|
||||||
|
|
|
@ -389,14 +389,15 @@ void VBForm::load_from_file(const String& path)
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto form_json = JsonValue::from_string(file_contents);
|
auto form_json = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(form_json.has_value());
|
||||||
|
|
||||||
if (!form_json.is_object()) {
|
if (!form_json.value().is_object()) {
|
||||||
GUI::MessageBox::show(String::format("Could not parse '%s'", path.characters()), "Error", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window());
|
GUI::MessageBox::show(String::format("Could not parse '%s'", path.characters()), "Error", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, window());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_name = form_json.as_object().get("name").to_string();
|
m_name = form_json.value().as_object().get("name").to_string();
|
||||||
auto widgets = form_json.as_object().get("widgets").as_array();
|
auto widgets = form_json.value().as_object().get("widgets").as_array();
|
||||||
|
|
||||||
widgets.for_each([&](const JsonValue& widget_value) {
|
widgets.for_each([&](const JsonValue& widget_value) {
|
||||||
auto& widget_object = widget_value.as_object();
|
auto& widget_object = widget_value.as_object();
|
||||||
|
|
|
@ -105,13 +105,13 @@ public:
|
||||||
auto request = m_socket->read(length);
|
auto request = m_socket->read(length);
|
||||||
|
|
||||||
auto request_json = JsonValue::from_string(request);
|
auto request_json = JsonValue::from_string(request);
|
||||||
if (!request_json.is_object()) {
|
if (!request_json.has_value() || !request_json.value().is_object()) {
|
||||||
dbg() << "RPC client sent invalid request";
|
dbg() << "RPC client sent invalid request";
|
||||||
shutdown();
|
shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_request(request_json.as_object());
|
handle_request(request_json.value().as_object());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
virtual ~RPCClient() override
|
virtual ~RPCClient() override
|
||||||
|
|
|
@ -48,7 +48,8 @@ HashMap<pid_t, Core::ProcessStatistics> ProcessStatisticsReader::get_all()
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents);
|
auto json = JsonValue::from_string(file_contents);
|
||||||
json.as_array().for_each([&](auto& value) {
|
ASSERT(json.has_value());
|
||||||
|
json.value().as_array().for_each([&](auto& value) {
|
||||||
const JsonObject& process_object = value.as_object();
|
const JsonObject& process_object = value.as_object();
|
||||||
Core::ProcessStatistics process;
|
Core::ProcessStatistics process;
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,9 @@ void JsonArrayModel::update()
|
||||||
|
|
||||||
auto json = JsonValue::from_string(file->read_all());
|
auto json = JsonValue::from_string(file->read_all());
|
||||||
|
|
||||||
ASSERT(json.is_array());
|
ASSERT(json.has_value());
|
||||||
m_array = json.as_array();
|
ASSERT(json.value().is_array());
|
||||||
|
m_array = json.value().as_array();
|
||||||
|
|
||||||
did_update();
|
did_update();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,9 @@ Optional<CharacterMapData> CharacterMapFile::load_from_file(const String& file_n
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_object();
|
auto json_result = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json_result.has_value());
|
||||||
|
auto json = json_result.value().as_object();
|
||||||
|
|
||||||
ByteBuffer map = read_map(json, "map");
|
ByteBuffer map = read_map(json, "map");
|
||||||
ByteBuffer shift_map = read_map(json, "shift_map");
|
ByteBuffer shift_map = read_map(json, "shift_map");
|
||||||
|
|
|
@ -56,7 +56,8 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
auto json = JsonValue::from_string(file->read_all());
|
auto json = JsonValue::from_string(file->read_all());
|
||||||
ASSERT(json.is_object());
|
ASSERT(json.has_value());
|
||||||
|
ASSERT(json.value().is_object());
|
||||||
|
|
||||||
out() << "#include <AK/Assertions.h>";
|
out() << "#include <AK/Assertions.h>";
|
||||||
out() << "#include <LibWeb/CSS/PropertyID.h>";
|
out() << "#include <LibWeb/CSS/PropertyID.h>";
|
||||||
|
@ -65,7 +66,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
out() << "PropertyID property_id_from_string(const StringView& string) {";
|
out() << "PropertyID property_id_from_string(const StringView& string) {";
|
||||||
|
|
||||||
json.as_object().for_each_member([&](auto& name, auto& value) {
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
ASSERT(value.is_object());
|
ASSERT(value.is_object());
|
||||||
out() << " if (string.equals_ignoring_case(\"" << name << "\"))";
|
out() << " if (string.equals_ignoring_case(\"" << name << "\"))";
|
||||||
out() << " return PropertyID::" << title_casify(name) << ";";
|
out() << " return PropertyID::" << title_casify(name) << ";";
|
||||||
|
@ -77,7 +78,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
out() << "const char* string_from_property_id(PropertyID property_id) {";
|
out() << "const char* string_from_property_id(PropertyID property_id) {";
|
||||||
out() << " switch (property_id) {";
|
out() << " switch (property_id) {";
|
||||||
json.as_object().for_each_member([&](auto& name, auto& value) {
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
ASSERT(value.is_object());
|
ASSERT(value.is_object());
|
||||||
out() << " case PropertyID::" << title_casify(name) << ":";
|
out() << " case PropertyID::" << title_casify(name) << ":";
|
||||||
out() << " return \"" << name << "\";";
|
out() << " return \"" << name << "\";";
|
||||||
|
|
|
@ -56,7 +56,8 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
auto json = JsonValue::from_string(file->read_all());
|
auto json = JsonValue::from_string(file->read_all());
|
||||||
ASSERT(json.is_object());
|
ASSERT(json.has_value());
|
||||||
|
ASSERT(json.value().is_object());
|
||||||
|
|
||||||
out() << "#pragma once";
|
out() << "#pragma once";
|
||||||
out() << "#include <AK/StringView.h>";
|
out() << "#include <AK/StringView.h>";
|
||||||
|
@ -67,7 +68,7 @@ int main(int argc, char** argv)
|
||||||
out() << "enum class PropertyID {";
|
out() << "enum class PropertyID {";
|
||||||
out() << " Invalid,";
|
out() << " Invalid,";
|
||||||
|
|
||||||
json.as_object().for_each_member([&](auto& name, auto& value) {
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
ASSERT(value.is_object());
|
ASSERT(value.is_object());
|
||||||
out() << " " << title_casify(name) << ",";
|
out() << " " << title_casify(name) << ",";
|
||||||
});
|
});
|
||||||
|
|
|
@ -140,9 +140,10 @@ private:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
||||||
auto file_contents = proc_memstat->read_all();
|
auto file_contents = proc_memstat->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_object();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
unsigned user_physical_allocated = json.get("user_physical_allocated").to_u32();
|
ASSERT(json.has_value());
|
||||||
unsigned user_physical_available = json.get("user_physical_available").to_u32();
|
unsigned user_physical_allocated = json.value().as_object().get("user_physical_allocated").to_u32();
|
||||||
|
unsigned user_physical_available = json.value().as_object().get("user_physical_available").to_u32();
|
||||||
allocated = (user_physical_allocated * 4096) / 1024;
|
allocated = (user_physical_allocated * 4096) / 1024;
|
||||||
available = (user_physical_available * 4096) / 1024;
|
available = (user_physical_available * 4096) / 1024;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
auto value = JsonValue::from_string("{\"property\": \"value\"}");
|
auto value = JsonValue::from_string("{\"property\": \"value\"}");
|
||||||
printf("parsed: _%s_\n", value.to_string().characters());
|
ASSERT(value.has_value());
|
||||||
printf("object.property = '%s'\n", value.as_object().get("property").to_string().characters());
|
printf("parsed: _%s_\n", value.value().to_string().characters());
|
||||||
|
printf("object.property = '%s'\n", value.value().as_object().get("property").to_string().characters());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,10 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json.has_value());
|
||||||
Vector<InterfaceDescriptor> ifnames;
|
Vector<InterfaceDescriptor> ifnames;
|
||||||
json.for_each([&ifnames](auto& value) {
|
json.value().as_array().for_each([&ifnames](auto& value) {
|
||||||
auto if_object = value.as_object();
|
auto if_object = value.as_object();
|
||||||
|
|
||||||
if (if_object.get("class_name").to_string() == "LoopbackAdapter")
|
if (if_object.get("class_name").to_string() == "LoopbackAdapter")
|
||||||
|
|
|
@ -39,8 +39,9 @@ int main()
|
||||||
|
|
||||||
printf("Address HWaddress\n");
|
printf("Address HWaddress\n");
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
json.for_each([](auto& value) {
|
ASSERT(json.has_value());
|
||||||
|
json.value().as_array().for_each([](auto& value) {
|
||||||
auto if_object = value.as_object();
|
auto if_object = value.as_object();
|
||||||
|
|
||||||
auto ip_address = if_object.get("ip_address").to_string();
|
auto ip_address = if_object.get("ip_address").to_string();
|
||||||
|
|
|
@ -86,7 +86,9 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json_result = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json_result.has_value());
|
||||||
|
auto json = json_result.value().as_array();
|
||||||
json.for_each([](auto& value) {
|
json.for_each([](auto& value) {
|
||||||
auto fs_object = value.as_object();
|
auto fs_object = value.as_object();
|
||||||
auto fs = fs_object.get("class_name").to_string();
|
auto fs = fs_object.get("class_name").to_string();
|
||||||
|
|
|
@ -74,6 +74,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents);
|
auto json = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json.has_value());
|
||||||
|
|
||||||
if (use_color) {
|
if (use_color) {
|
||||||
color_name = "\033[33;1m";
|
color_name = "\033[33;1m";
|
||||||
|
@ -86,7 +87,7 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> trail;
|
Vector<String> trail;
|
||||||
print("json", json, trail);
|
print("json", json.value(), trail);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +117,6 @@ static void print(const String& name, const JsonValue& value, Vector<String>& tr
|
||||||
}
|
}
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case JsonValue::Type::Null:
|
case JsonValue::Type::Null:
|
||||||
case JsonValue::Type::Undefined:
|
|
||||||
printf("%s", color_null);
|
printf("%s", color_null);
|
||||||
break;
|
break;
|
||||||
case JsonValue::Type::Bool:
|
case JsonValue::Type::Bool:
|
||||||
|
|
|
@ -72,8 +72,9 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
json.for_each([](auto& value) {
|
ASSERT(json.has_value());
|
||||||
|
json.value().as_array().for_each([](auto& value) {
|
||||||
auto if_object = value.as_object();
|
auto if_object = value.as_object();
|
||||||
|
|
||||||
auto name = if_object.get("name").to_string();
|
auto name = if_object.get("name").to_string();
|
||||||
|
|
|
@ -63,8 +63,9 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto file_contents = file->read_all();
|
auto file_contents = file->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents);
|
auto json = JsonValue::from_string(file_contents);
|
||||||
|
ASSERT(json.has_value());
|
||||||
|
|
||||||
print(json);
|
print(json.value());
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -101,7 +102,7 @@ void print(const JsonValue& value, int indent)
|
||||||
printf("\033[35;1m");
|
printf("\033[35;1m");
|
||||||
else if (value.is_bool())
|
else if (value.is_bool())
|
||||||
printf("\033[32;1m");
|
printf("\033[32;1m");
|
||||||
else if (value.is_null() || value.is_undefined())
|
else if (value.is_null())
|
||||||
printf("\033[34;1m");
|
printf("\033[34;1m");
|
||||||
if (value.is_string())
|
if (value.is_string())
|
||||||
putchar('"');
|
putchar('"');
|
||||||
|
|
|
@ -60,8 +60,9 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
printf("%4s %-10s\n", " ", "CPU0");
|
printf("%4s %-10s\n", " ", "CPU0");
|
||||||
auto file_contents = proc_interrupts->read_all();
|
auto file_contents = proc_interrupts->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
json.for_each([](auto& value) {
|
ASSERT(json.has_value());
|
||||||
|
json.value().as_array().for_each([](auto& value) {
|
||||||
auto handler = value.as_object();
|
auto handler = value.as_object();
|
||||||
auto purpose = handler.get("purpose").to_string();
|
auto purpose = handler.get("purpose").to_string();
|
||||||
auto interrupt = handler.get("interrupt_line").to_string();
|
auto interrupt = handler.get("interrupt_line").to_string();
|
||||||
|
|
|
@ -69,8 +69,9 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_contents = proc_pci->read_all();
|
auto file_contents = proc_pci->read_all();
|
||||||
auto json = JsonValue::from_string(file_contents).as_array();
|
auto json = JsonValue::from_string(file_contents);
|
||||||
json.for_each([db](auto& value) {
|
ASSERT(json.has_value());
|
||||||
|
json.value().as_array().for_each([db](auto& value) {
|
||||||
auto dev = value.as_object();
|
auto dev = value.as_object();
|
||||||
auto seg = dev.get("seg").to_u32();
|
auto seg = dev.get("seg").to_u32();
|
||||||
auto bus = dev.get("bus").to_u32();
|
auto bus = dev.get("bus").to_u32();
|
||||||
|
|
|
@ -149,9 +149,10 @@ bool print_mounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
auto content = df->read_all();
|
auto content = df->read_all();
|
||||||
auto json = JsonValue::from_string(content).as_array();
|
auto json = JsonValue::from_string(content);
|
||||||
|
ASSERT(json.has_value());
|
||||||
|
|
||||||
json.for_each([](auto& value) {
|
json.value().as_array().for_each([](auto& value) {
|
||||||
auto fs_object = value.as_object();
|
auto fs_object = value.as_object();
|
||||||
auto class_name = fs_object.get("class_name").to_string();
|
auto class_name = fs_object.get("class_name").to_string();
|
||||||
auto mount_point = fs_object.get("mount_point").to_string();
|
auto mount_point = fs_object.get("mount_point").to_string();
|
||||||
|
|
Loading…
Reference in a new issue