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. :^)
This commit is contained in:
Andreas Kling 2020-02-15 12:04:35 +01:00
parent dc417ada6d
commit a4d857e3c5
12 changed files with 272 additions and 61 deletions

View file

@ -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;

View file

@ -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;
}

View file

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

View file

@ -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;
}
}

View file

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

View file

@ -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;
}
}

View file

@ -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&);
}

View file

@ -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;
}
}

View file

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

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

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