From 014f8ca8c4a2b94ed177f9cdbe308aecaadc7f8a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 29 Oct 2019 16:36:50 +0100 Subject: [PATCH] AK: Allow JsonValue to store 64-bit integers internally Add dedicated internal types for Int64 and UnsignedInt64. This makes it a bit more straightforward to work with 64-bit numbers (instead of just implicitly storing them as doubles.) --- AK/JsonObject.h | 14 ++- AK/JsonValue.cpp | 23 +++-- AK/JsonValue.h | 122 ++++++++++++++------------- Kernel/FileSystem/ProcFS.cpp | 20 ++--- Libraries/LibGUI/GJsonArrayModel.cpp | 6 +- Libraries/LibGUI/GVariant.cpp | 22 ++++- 6 files changed, 120 insertions(+), 87 deletions(-) diff --git a/AK/JsonObject.h b/AK/JsonObject.h index 439f560aae..a69d2255b9 100644 --- a/AK/JsonObject.h +++ b/AK/JsonObject.h @@ -120,11 +120,17 @@ void JsonValue::serialize(Builder& builder) const builder.appendf("%g", m_value.as_double); break; #endif - case Type::Int: - builder.appendf("%d", m_value.as_int); + case Type::Int32: + builder.appendf("%d", as_i32()); break; - case Type::UnsignedInt: - builder.appendf("%u", m_value.as_uint); + case Type::Int64: + builder.appendf("%lld", as_i64()); + break; + case Type::UnsignedInt32: + builder.appendf("%u", as_u32()); + break; + case Type::UnsignedInt64: + builder.appendf("%llu", as_u64()); break; case Type::Undefined: builder.append("undefined"); diff --git a/AK/JsonValue.cpp b/AK/JsonValue.cpp index 0bbf9b7458..9a573398f4 100644 --- a/AK/JsonValue.cpp +++ b/AK/JsonValue.cpp @@ -63,21 +63,28 @@ JsonValue& JsonValue::operator=(JsonValue&& other) return *this; } -JsonValue::JsonValue(int value) - : m_type(Type::Int) +JsonValue::JsonValue(i32 value) + : m_type(Type::Int32) { - m_value.as_int = value; + m_value.as_i32 = value; } -JsonValue::JsonValue(long unsigned value) - : JsonValue((unsigned)value) +JsonValue::JsonValue(u32 value) + : m_type(Type::UnsignedInt32) { + m_value.as_u32 = value; } -JsonValue::JsonValue(unsigned value) - : m_type(Type::UnsignedInt) +JsonValue::JsonValue(i64 value) + : m_type(Type::Int64) { - m_value.as_uint = value; + m_value.as_i64 = value; +} + +JsonValue::JsonValue(u64 value) + : m_type(Type::UnsignedInt64) +{ + m_value.as_u64 = value; } JsonValue::JsonValue(const char* cstring) diff --git a/AK/JsonValue.h b/AK/JsonValue.h index 0ca665f6c5..92784407db 100644 --- a/AK/JsonValue.h +++ b/AK/JsonValue.h @@ -1,8 +1,8 @@ #pragma once -#include #include #include +#include #include namespace AK { @@ -16,8 +16,10 @@ public: enum class Type { Undefined, Null, - Int, - UnsignedInt, + Int32, + UnsignedInt32, + Int64, + UnsignedInt64, #ifndef KERNEL Double, #endif @@ -38,9 +40,11 @@ public: JsonValue& operator=(const JsonValue&); JsonValue& operator=(JsonValue&&); - JsonValue(int); - JsonValue(unsigned); - JsonValue(long unsigned); + JsonValue(i32); + JsonValue(u32); + JsonValue(i64); + JsonValue(u64); + #ifndef KERNEL JsonValue(double); #endif @@ -84,31 +88,11 @@ public: return IPv4Address::from_string(as_string()); } - int to_int(int default_value = 0) const - { - if (!is_number()) - return default_value; -#ifndef KERNEL - if (is_double()) - return (int)as_double(); -#endif - if (is_uint()) - return (int)as_uint(); - return as_int(); - } + int to_int(int default_value = 0) const { return to_i32(default_value); } + i32 to_i32(i32 default_value = 0) const { return to_number(default_value); } - unsigned to_uint(unsigned default_value = 0) const - { - if (!is_number()) - return default_value; -#ifndef KERNEL - if (is_double()) - return (unsigned)as_double(); -#endif - if (is_int()) - return (unsigned)as_int(); - return as_uint(); - } + unsigned to_uint(unsigned default_value = 0) const { return to_u32(default_value); } + u32 to_u32(u32 default_value = 0) const { return to_number(default_value); } bool to_bool(bool default_value = false) const { @@ -117,16 +101,28 @@ public: return as_bool(); } - int as_int() const + int as_i32() const { - ASSERT(is_int()); - return m_value.as_int; + ASSERT(is_i32()); + return m_value.as_i32; } - int as_uint() const + int as_u32() const { - ASSERT(is_uint()); - return m_value.as_uint; + ASSERT(is_u32()); + return m_value.as_u32; + } + + int as_i64() const + { + ASSERT(is_i64()); + return m_value.as_i64; + } + + int as_u64() const + { + ASSERT(is_u64()); + return m_value.as_u64; } int as_bool() const @@ -170,8 +166,10 @@ public: bool is_undefined() const { return m_type == Type::Undefined; } bool is_bool() const { return m_type == Type::Bool; } bool is_string() const { return m_type == Type::String; } - bool is_int() const { return m_type == Type::Int; } - bool is_uint() const { return m_type == Type::UnsignedInt; } + bool is_i32() const { return m_type == Type::Int32; } + bool is_u32() const { return m_type == Type::UnsignedInt32; } + bool is_i64() const { return m_type == Type::Int64; } + bool is_u64() const { return m_type == Type::UnsignedInt64; } #ifndef KERNEL bool is_double() const { @@ -185,28 +183,36 @@ public: bool is_object() const { return m_type == Type::Object; } bool is_number() const { - if (m_type == Type::Int || m_type == Type::UnsignedInt) - return true; -#ifdef KERNEL - return false; -#else - return m_type == Type::Double; + switch (m_type) { + case Type::Int32: + case Type::UnsignedInt32: + case Type::Int64: + case Type::UnsignedInt64: +#ifndef KERNEL + case Type::Double: #endif + return true; + default: + return false; + } } - u32 to_u32(u32 default_value = 0) const + template + T to_number(T default_value = 0) const { - if (!is_number()) - return default_value; -#ifdef KERNEL - return (u32)m_value.as_int; -#else - if (type() == Type::Int) - return (u32)m_value.as_int; - if (type() == Type::UnsignedInt) - return m_value.as_uint; - return (u32)m_value.as_double; +#ifndef KERNEL + if (is_double()) + return (T)as_double(); #endif + if (type() == Type::Int32) + return (T)as_i32(); + if (type() == Type::UnsignedInt32) + return (T)as_u32(); + if (type() == Type::Int64) + return (T)as_i64(); + if (type() == Type::UnsignedInt64) + return (T)as_u64(); + return default_value; } private: @@ -222,8 +228,10 @@ private: #ifndef KERNEL double as_double; #endif - int as_int; - unsigned int as_uint; + i32 as_i32; + u32 as_u32; + i64 as_i64; + u64 as_u64; bool as_bool; } m_value; }; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 15af20a357..b76bff451f 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -257,8 +257,8 @@ Optional procfs$pid_vm(InodeIdentifier identifier) region_object.add("readable", region.is_readable()); region_object.add("writable", region.is_writable()); region_object.add("address", region.vaddr().get()); - region_object.add("size", region.size()); - region_object.add("amount_resident", region.amount_resident()); + region_object.add("size", (u32)region.size()); + region_object.add("amount_resident", (u32)region.amount_resident()); region_object.add("name", region.name()); } array.finish(); @@ -644,9 +644,9 @@ Optional procfs$memstat(InodeIdentifier) InterruptDisabler disabler; KBufferBuilder builder; JsonObjectSerializer json { builder }; - json.add("kmalloc_allocated", sum_alloc); - json.add("kmalloc_available", sum_free); - json.add("kmalloc_eternal_allocated", kmalloc_sum_eternal); + json.add("kmalloc_allocated", (u32)sum_alloc); + json.add("kmalloc_available", (u32)sum_free); + json.add("kmalloc_eternal_allocated", (u32)kmalloc_sum_eternal); json.add("user_physical_allocated", MM.user_physical_pages_used()); json.add("user_physical_available", MM.user_physical_pages()); json.add("super_physical_allocated", MM.super_physical_pages_used()); @@ -655,8 +655,8 @@ Optional procfs$memstat(InodeIdentifier) json.add("kfree_call_count", g_kfree_call_count); slab_alloc_stats([&json](size_t slab_size, size_t num_allocated, size_t num_free) { auto prefix = String::format("slab_%zu", slab_size); - json.add(String::format("%s_num_allocated", prefix.characters()), num_allocated); - json.add(String::format("%s_num_free", prefix.characters()), num_free); + json.add(String::format("%s_num_allocated", prefix.characters()), (u32)num_allocated); + json.add(String::format("%s_num_free", prefix.characters()), (u32)num_free); }); json.finish(); return builder.build(); @@ -684,9 +684,9 @@ Optional procfs$all(InodeIdentifier) process_object.add("nfds", process.number_of_open_file_descriptors()); process_object.add("name", process.name()); process_object.add("tty", process.tty() ? process.tty()->tty_name() : "notty"); - process_object.add("amount_virtual", process.amount_virtual()); - process_object.add("amount_resident", process.amount_resident()); - process_object.add("amount_shared", process.amount_shared()); + process_object.add("amount_virtual", (u32)process.amount_virtual()); + process_object.add("amount_resident", (u32)process.amount_resident()); + process_object.add("amount_shared", (u32)process.amount_shared()); process_object.add("ticks", process.main_thread().ticks()); process_object.add("priority", to_string(process.priority())); process_object.add("syscall_count", process.syscall_count()); diff --git a/Libraries/LibGUI/GJsonArrayModel.cpp b/Libraries/LibGUI/GJsonArrayModel.cpp index 9a6a7dbc36..3f9f356141 100644 --- a/Libraries/LibGUI/GJsonArrayModel.cpp +++ b/Libraries/LibGUI/GJsonArrayModel.cpp @@ -34,10 +34,8 @@ GVariant GJsonArrayModel::data(const GModelIndex& index, Role role) const auto data = object.get(json_field_name); if (field_spec.massage_for_display) return field_spec.massage_for_display(object); - if (data.is_int()) - return data.as_int(); - if (data.is_uint()) - return data.as_uint(); + if (data.is_number()) + return data.to_i32(); return object.get(json_field_name).to_string(); } diff --git a/Libraries/LibGUI/GVariant.cpp b/Libraries/LibGUI/GVariant.cpp index 87f9b3a4fd..1ca483b084 100644 --- a/Libraries/LibGUI/GVariant.cpp +++ b/Libraries/LibGUI/GVariant.cpp @@ -93,15 +93,29 @@ GVariant::GVariant(const JsonValue& value) return; } - if (value.is_int()) { + if (value.is_i32()) { m_type = Type::Int; - m_value.as_int = value.as_int(); + m_value.as_int = value.as_i32(); return; } - if (value.is_uint()) { + if (value.is_u32()) { m_type = Type::UnsignedInt; - m_value.as_uint = value.as_uint(); + m_value.as_uint = value.as_u32(); + return; + } + + if (value.is_i64()) { + // FIXME: GVariant should have a 64-bit internal type. + m_type = Type::Int; + m_value.as_int = value.to_i32(); + return; + } + + if (value.is_u64()) { + // FIXME: GVariant should have a 64-bit internal type. + m_type = Type::UnsignedInt; + m_value.as_uint = value.to_u32(); return; }