ソースを参照

LibIPC+IPCCompiler: Add IPC::Decoder, let classes decode themselves

This shaves ~5 seconds off of a full build, not too bad. Also it just
seems nicer to push this logic out to classes. It could be better but
it's a start. :^)
Andreas Kling 5 年 前
コミット
a4d857e3c5

+ 9 - 60
DevTools/IPCCompiler/main.cpp

@@ -228,6 +228,7 @@ int main(int argc, char** argv)
     dbg() << "#include <AK/OwnPtr.h>";
     dbg() << "#include <LibGfx/Color.h>";
     dbg() << "#include <LibGfx/Rect.h>";
+    dbg() << "#include <LibIPC/Decoder.h>";
     dbg() << "#include <LibIPC/Encoder.h>";
     dbg() << "#include <LibIPC/Endpoint.h>";
     dbg() << "#include <LibIPC/Message.h>";
@@ -300,8 +301,7 @@ int main(int argc, char** argv)
             dbg() << "    static OwnPtr<" << name << "> decode(BufferStream& stream, size_t& size_in_bytes)";
             dbg() << "    {";
 
-            if (parameters.is_empty())
-                dbg() << "        (void)stream;";
+            dbg() << "        IPC::Decoder decoder(stream);";
 
             for (auto& parameter : parameters) {
                 String initial_value = "{}";
@@ -309,70 +309,19 @@ int main(int argc, char** argv)
                     initial_value = "false";
                 dbg() << "        " << parameter.type << " " << parameter.name << " = " << initial_value << ";";
 
-                if (parameter.type == "String") {
-                    dbg() << "        i32 " << parameter.name << "_length = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_length;";
-                    dbg() << "        if (" << parameter.name << "_length == 0) {";
-                    dbg() << "            " << parameter.name << " = String::empty();";
-                    dbg() << "        } else if (" << parameter.name << "_length < 0) {";
-                    dbg() << "            " << parameter.name << " = String();";
-                    dbg() << "        } else {";
-                    dbg() << "            char* " << parameter.name << "_buffer = nullptr;";
-                    dbg() << "            auto " << parameter.name << "_impl = StringImpl::create_uninitialized(static_cast<size_t>(" << parameter.name << "_length), " << parameter.name << "_buffer);";
-                    dbg() << "            for (size_t i = 0; i < static_cast<size_t>(" << parameter.name << "_length); ++i) {";
-                    dbg() << "                stream >> " << parameter.name << "_buffer[i];";
-                    dbg() << "            }";
-                    dbg() << "            " << parameter.name << " = *" << parameter.name << "_impl;";
-                    dbg() << "        }";
-                } else if (parameter.type == "Gfx::Color") {
-                    dbg() << "        u32 " << parameter.name << "_rgba = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_rgba;";
-                    dbg() << "        " << parameter.name << " = Gfx::Color::from_rgba(" << parameter.name << "_rgba);";
-                } else if (parameter.type == "Gfx::Size") {
-                    dbg() << "        int " << parameter.name << "_width = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_width;";
-                    dbg() << "        int " << parameter.name << "_height = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_height;";
-                    dbg() << "        " << parameter.name << " = { " << parameter.name << "_width, " << parameter.name << "_height };";
-                } else if (parameter.type == "Gfx::Point") {
-                    dbg() << "        int " << parameter.name << "_x = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_x;";
-                    dbg() << "        int " << parameter.name << "_y = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_y;";
-                    dbg() << "        " << parameter.name << " = { " << parameter.name << "_x, " << parameter.name << "_y };";
-                } else if (parameter.type == "Gfx::Rect") {
-                    dbg() << "        int " << parameter.name << "_x = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_x;";
-                    dbg() << "        int " << parameter.name << "_y = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_y;";
-                    dbg() << "        int " << parameter.name << "_width = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_width;";
-                    dbg() << "        int " << parameter.name << "_height = 0;";
-                    dbg() << "        stream >> " << parameter.name << "_height;";
-                    dbg() << "        " << parameter.name << " = { " << parameter.name << "_x, " << parameter.name << "_y, " << parameter.name << "_width, " << parameter.name << "_height };";
-                } else if (parameter.type == "Vector<Gfx::Rect>") {
+                if (parameter.type == "Vector<Gfx::Rect>") {
                     dbg() << "        int " << parameter.name << "_size = 0;";
                     dbg() << "        stream >> " << parameter.name << "_size;";
                     dbg() << "        for (int i = 0; i < " << parameter.name << "_size; ++i) {";
-                    dbg() << "            int " << parameter.name << "_x = 0;";
-                    dbg() << "            stream >> " << parameter.name << "_x;";
-                    dbg() << "            int " << parameter.name << "_y = 0;";
-                    dbg() << "            stream >> " << parameter.name << "_y;";
-                    dbg() << "            int " << parameter.name << "_width = 0;";
-                    dbg() << "            stream >> " << parameter.name << "_width;";
-                    dbg() << "            int " << parameter.name << "_height = 0;";
-                    dbg() << "            stream >> " << parameter.name << "_height;";
-                    dbg() << "            " << parameter.name << ".empend(" << parameter.name << "_x, " << parameter.name << "_y, " << parameter.name << "_width, " << parameter.name << "_height);";
+                    dbg() << "            Gfx::Rect rect;";
+                    dbg() << "            if (!decoder.decode(rect))";
+                    dbg() << "                return nullptr;";
+                    dbg() << "            " << parameter.name << ".append(move(rect));";
                     dbg() << "        }";
                 } else {
-                    dbg() << "        stream >> " << parameter.name << ";";
+                    dbg() << "        if (!decoder.decode(" << parameter.name << "))";
+                    dbg() << "            return nullptr;";
                 }
-                dbg() << "        if (stream.handle_read_failure()) {";
-#ifdef GENERATE_DEBUG_CODE
-                dbg() << "            dbg() << \"Failed to decode " << name << "." << parameter.name << "\";";
-#endif
-                dbg() << "            return nullptr;";
-                dbg() << "        }";
             }
 
             StringBuilder builder;

+ 12 - 1
Libraries/LibGfx/Color.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <AK/Assertions.h>
+#include <AK/BufferStream.h>
 #include <AK/Optional.h>
 #include <AK/String.h>
 #include <LibGfx/Color.h>
@@ -344,7 +345,17 @@ Optional<Color> Color::from_string(const StringView& string)
 }
 }
 
-inline const LogStream& operator<<(const LogStream& stream, Color value)
+const LogStream& operator<<(const LogStream& stream, Color value)
 {
     return stream << value.to_string();
 }
+
+bool IPC::decode(BufferStream& stream, Color& color)
+{
+    u32 rgba;
+    stream >> rgba;
+    if (stream.handle_read_failure())
+        return false;
+    color = Color::from_rgba(rgba);
+    return true;
+}

+ 4 - 0
Libraries/LibGfx/Color.h

@@ -278,3 +278,7 @@ const LogStream& operator<<(const LogStream&, Color);
 }
 
 using Gfx::Color;
+
+namespace IPC {
+bool decode(BufferStream&, Gfx::Color&);
+}

+ 17 - 0
Libraries/LibGfx/Point.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/BufferStream.h>
 #include <AK/String.h>
 #include <LibGfx/Point.h>
 
@@ -40,3 +41,19 @@ const LogStream& operator<<(const LogStream& stream, const Point& value)
 }
 
 }
+
+namespace IPC {
+
+bool decode(BufferStream& stream, Gfx::Point& point)
+{
+    int x;
+    int y;
+    stream >> x;
+    stream >> y;
+    if (stream.handle_read_failure())
+        return false;
+    point = { x, y };
+    return true;
+}
+
+}

+ 4 - 0
Libraries/LibGfx/Point.h

@@ -159,3 +159,7 @@ private:
 const LogStream& operator<<(const LogStream&, const Point&);
 
 }
+
+namespace IPC {
+bool decode(BufferStream&, Gfx::Point&);
+}

+ 16 - 0
Libraries/LibGfx/Rect.cpp

@@ -142,3 +142,19 @@ const LogStream& operator<<(const LogStream& stream, const Rect& value)
 }
 
 }
+
+namespace IPC {
+
+bool decode(BufferStream& stream, Gfx::Rect& rect)
+{
+    Gfx::Point point;
+    Gfx::Size size;
+    if (!decode(stream, point))
+        return false;
+    if (!decode(stream, size))
+        return false;
+    rect = { point, size };
+    return true;
+}
+
+}

+ 4 - 0
Libraries/LibGfx/Rect.h

@@ -334,3 +334,7 @@ inline void Point::constrain(const Rect& rect)
 const LogStream& operator<<(const LogStream&, const Rect&);
 
 }
+
+namespace IPC {
+bool decode(BufferStream&, Gfx::Rect&);
+}

+ 17 - 0
Libraries/LibGfx/Size.cpp

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <AK/BufferStream.h>
 #include <AK/String.h>
 #include <LibGfx/Size.h>
 
@@ -40,3 +41,19 @@ const LogStream& operator<<(const LogStream& stream, const Size& value)
 }
 
 }
+
+namespace IPC {
+
+bool decode(BufferStream& stream, Gfx::Size& size)
+{
+    int width;
+    int height;
+    stream >> width;
+    stream >> height;
+    if (stream.handle_read_failure())
+        return false;
+    size = { width, height };
+    return true;
+}
+
+}

+ 4 - 0
Libraries/LibGfx/Size.h

@@ -111,3 +111,7 @@ private:
 const LogStream& operator<<(const LogStream&, const Size&);
 
 }
+
+namespace IPC {
+bool decode(BufferStream&, Gfx::Size&);
+}

+ 115 - 0
Libraries/LibIPC/Decoder.cpp

@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/BufferStream.h>
+#include <LibIPC/Decoder.h>
+
+namespace IPC {
+
+bool Decoder::decode(bool& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(u8& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(u16& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(u32& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(u64& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(i8& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(i16& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(i32& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(i64& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(float& value)
+{
+    m_stream >> value;
+    return !m_stream.handle_read_failure();
+}
+
+bool Decoder::decode(String& value)
+{
+    i32 length = 0;
+    m_stream >> length;
+    if (m_stream.handle_read_failure())
+        return false;
+    if (length < 0) {
+        value = {};
+        return true;
+    }
+    if (length == 0) {
+        value = String::empty();
+        return true;
+    }
+    char* text_buffer = nullptr;
+    auto text_impl = StringImpl::create_uninitialized(static_cast<size_t>(length), text_buffer);
+    for (size_t i = 0; i < static_cast<size_t>(length); ++i) {
+        m_stream >> text_buffer[i];
+    }
+    value = *text_impl;
+    return !m_stream.handle_read_failure();
+}
+
+}

+ 69 - 0
Libraries/LibIPC/Decoder.h

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Forward.h>
+#include <LibIPC/Message.h>
+
+namespace IPC {
+
+template<typename T>
+bool decode(BufferStream&, T&)
+{
+    return false;
+}
+
+class Decoder {
+public:
+    explicit Decoder(BufferStream& stream)
+        : m_stream(stream)
+    {
+    }
+
+    bool decode(bool&);
+    bool decode(u8&);
+    bool decode(u16&);
+    bool decode(u32&);
+    bool decode(u64&);
+    bool decode(i8&);
+    bool decode(i16&);
+    bool decode(i32&);
+    bool decode(i64&);
+    bool decode(float&);
+    bool decode(String&);
+
+    template<typename T>
+    bool decode(T& value)
+    {
+        return IPC::decode(m_stream, value);
+    }
+
+private:
+    BufferStream& m_stream;
+};
+
+}

+ 1 - 0
Libraries/LibIPC/Makefile

@@ -1,4 +1,5 @@
 OBJS = \
+    Decoder.o \
     Encoder.o \
     Endpoint.o \
     Message.o