Added arrays to queues.
Change-Id: Ifcb5ff0ecdbd47e7fa445275195cd7a87e96c20a
diff --git a/aos/common/common.gyp b/aos/common/common.gyp
index fb410b7..9a63e48 100644
--- a/aos/common/common.gyp
+++ b/aos/common/common.gyp
@@ -109,6 +109,7 @@
'<(EXTERNALS):gtest',
'test_queue',
'<(AOS)/build/aos.gyp:logging',
+ 'queue_testutils',
],
},
{
diff --git a/aos/common/queue_types.cc b/aos/common/queue_types.cc
index 42dec0c..f04e365 100644
--- a/aos/common/queue_types.cc
+++ b/aos/common/queue_types.cc
@@ -43,6 +43,8 @@
for (int i = 0; i < number_fields; ++i) {
to_network(&fields[i]->type, buffer);
buffer += sizeof(fields[i]->type);
+ to_network(&fields[i]->length, buffer);
+ buffer += sizeof(fields[i]->length);
length = fields[i]->name.size();
to_network(&length, buffer);
buffer += sizeof(length);
@@ -53,7 +55,8 @@
return buffer - buffer_start;
}
-MessageType *MessageType::Deserialize(const char *buffer, size_t *bytes) {
+MessageType *MessageType::Deserialize(const char *buffer, size_t *bytes,
+ bool deserialize_length) {
uint16_t name_length;
decltype(MessageType::super_size) super_size;
decltype(MessageType::id) id;
@@ -94,6 +97,10 @@
to_host(buffer, &fields[i]->type);
buffer += sizeof(fields[i]->type);
+ if (deserialize_length) {
+ to_host(buffer, &fields[i]->length);
+ buffer += sizeof(fields[i]->length);
+ }
to_host(buffer, &field_name_length);
buffer += sizeof(field_name_length);
@@ -108,6 +115,50 @@
return r.release();
}
+bool PrintArray(char *output, size_t *output_bytes, const void *input,
+ size_t *input_bytes, uint32_t type_id, uint32_t length) {
+ if (*output_bytes < 1) return false;
+ *output_bytes -= 1;
+ *(output++) = '[';
+
+ bool first = true;
+ for (uint32_t i = 0; i < length; ++i) {
+ if (first) {
+ first = false;
+ } else {
+ if (*output_bytes < 2) return false;
+ *output_bytes -= 2;
+ *(output++) = ',';
+ *(output++) = ' ';
+ }
+
+ const size_t output_bytes_before = *output_bytes,
+ input_bytes_before = *input_bytes;
+ if (MessageType::IsPrimitive(type_id)) {
+ if (!PrintField(output, output_bytes, input, input_bytes, type_id)) {
+ return false;
+ }
+ } else {
+ if (!PrintMessage(output, output_bytes, input, input_bytes,
+ type_cache::Get(type_id))) {
+ return false;
+ }
+ // Ignore the trailing '\0' that the subcall put on.
+ *output_bytes += 1;
+ }
+
+ // Update the input and output pointers.
+ output += output_bytes_before - *output_bytes;
+ input =
+ static_cast<const char *>(input) + input_bytes_before - *input_bytes;
+ }
+ if (*output_bytes < 2) return false;
+ *output_bytes -= 2;
+ *(output++) = ']';
+ *(output++) = '\0';
+ return true;
+}
+
bool PrintMessage(char *output, size_t *output_bytes, const void *input,
size_t *input_bytes, const MessageType &type) {
*input_bytes -= type.super_size;
@@ -138,14 +189,21 @@
const size_t output_bytes_before = *output_bytes,
input_bytes_before = *input_bytes;
- if (MessageType::IsPrimitive(type.fields[i]->type)) {
- if (!PrintField(output, output_bytes, input, input_bytes,
- type.fields[i]->type)) {
+ const uint32_t type_id = type.fields[i]->type;
+ if (type.fields[i]->length > 0) {
+ if (!PrintArray(output, output_bytes, input, input_bytes, type_id,
+ type.fields[i]->length)) {
+ return false;
+ }
+ // Ignore the trailing '\0' that the subcall put on.
+ *output_bytes += 1;
+ } else if (MessageType::IsPrimitive(type_id)) {
+ if (!PrintField(output, output_bytes, input, input_bytes, type_id)) {
return false;
}
} else {
if (!PrintMessage(output, output_bytes, input, input_bytes,
- type_cache::Get(type.fields[i]->type))) {
+ type_cache::Get(type_id))) {
return false;
}
// Ignore the trailing '\0' that the subcall put on.
diff --git a/aos/common/queue_types.h b/aos/common/queue_types.h
index 7381029..be943c1 100644
--- a/aos/common/queue_types.h
+++ b/aos/common/queue_types.h
@@ -21,6 +21,8 @@
struct Field {
// The type ID for the type of this field.
uint32_t type;
+ // The length of the array if it is one or 0.
+ uint32_t length;
::std::string name;
};
@@ -47,8 +49,11 @@
ssize_t Serialize(char *buffer, size_t max_bytes) const;
// bytes should start out as the number of bytes available in buffer and gets
// reduced by the number actually read before returning.
+ // deserialize_length is whether to look for a length field in the serialized
+ // data.
// Returns a new instance allocated with new or nullptr for error.
- static MessageType *Deserialize(const char *buffer, size_t *bytes);
+ static MessageType *Deserialize(const char *buffer, size_t *bytes,
+ bool deserialize_length = true);
static bool IsPrimitive(uint32_t type_id) {
return (type_id & 0x2000) != 0;
diff --git a/aos/common/queue_types_test.cc b/aos/common/queue_types_test.cc
index 514499b..868820f 100644
--- a/aos/common/queue_types_test.cc
+++ b/aos/common/queue_types_test.cc
@@ -10,10 +10,12 @@
#include "aos/common/byteorder.h"
#include "aos/queue_primitives.h"
#include "aos/common/logging/logging.h"
+#include "aos/common/queue_testutils.h"
using ::aos::common::testing::Structure;
using ::aos::common::testing::MessageWithStructure;
using ::aos::common::testing::OtherTestingMessage;
+using ::aos::common::testing::MessageWithArrays;
namespace aos {
namespace testing {
@@ -21,12 +23,16 @@
typedef MessageType::Field Field;
static const MessageType kTestType1(5, 0x1234, "TestType1",
- {new Field{0, "field1"},
- new Field{0, "field2"},
- new Field{0, "field3"}});
+ {new Field{0, 0, "field1"},
+ new Field{0, 0, "field2"},
+ new Field{0, 0, "field3"}});
class QueueTypesTest : public ::testing::Test {
public:
+ QueueTypesTest() {
+ ::aos::common::testing::EnableTestLogging();
+ }
+
::testing::AssertionResult Equal(const MessageType &l, const MessageType &r) {
using ::testing::AssertionFailure;
if (l.id != r.id) {
@@ -83,7 +89,7 @@
class PrintMessageTest : public ::testing::Test {
public:
- char input[128], output[128];
+ char input[128], output[256];
size_t input_bytes, output_bytes;
};
@@ -194,6 +200,15 @@
static const ::std::string kTestStructure1String =
".aos.common.testing.Structure{struct_bool:f, struct_int:973"
", struct_float:8.560000}";
+static const ::aos::common::testing::Structure kStructureValue(true, 973, 3.14);
+static const MessageWithArrays kTestMessageWithArrays({{971, 254, 1678}},
+ {{kStructureValue,
+ kStructureValue}});
+static const ::std::string kTestMessageWithArraysString =
+ ".aos.common.testing.MessageWithArrays{test_int:[971, 254, 1678], "
+ "test_struct:[.aos.common.testing.Structure{struct_bool:T, struct_int:973, "
+ "struct_float:3.140000}, .aos.common.testing.Structure{struct_bool:T, "
+ "struct_int:973, struct_float:3.140000}]}";
TEST_F(PrintMessageTest, Basic) {
CHECK_GE(sizeof(input), kTestMessage1.Size());
@@ -244,5 +259,16 @@
EXPECT_EQ(kOutput.size() + 1, sizeof(output) - output_bytes);
}
+TEST_F(PrintMessageTest, Array) {
+ CHECK_GE(sizeof(input), kTestMessageWithArrays.Size());
+ input_bytes = kTestMessageWithArrays.Serialize(input);
+ output_bytes = sizeof(output);
+ ASSERT_TRUE(PrintMessage(output, &output_bytes, input, &input_bytes,
+ *kTestMessageWithArrays.GetType()));
+ EXPECT_EQ(kTestMessageWithArraysString, ::std::string(output));
+ EXPECT_EQ(kTestMessageWithArraysString.size() + 1,
+ sizeof(output) - output_bytes);
+}
+
} // namespace testing
} // namespace aos
diff --git a/aos/common/test_queue.q b/aos/common/test_queue.q
index d603802..827b607 100644
--- a/aos/common/test_queue.q
+++ b/aos/common/test_queue.q
@@ -23,6 +23,11 @@
double test_double;
};
+message MessageWithArrays {
+ uint16_t[3] test_int;
+ Structure[2] test_struct;
+};
+
queue TestingMessage test_queue;
queue_group TwoQueues {