dbus: fix base class of ErrorResponse
[chromium-blink-merge.git] / dbus / message.cc
blob43fb3bb8b593718b6fc01961c1f97a705f66fde8
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "dbus/message.h"
7 #include <string>
9 #include "base/basictypes.h"
10 #include "base/format_macros.h"
11 #include "base/logging.h"
12 #include "base/stringprintf.h"
13 #include "dbus/object_path.h"
14 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
16 namespace {
18 // Appends the header name and the value to |output|, if the value is
19 // not empty.
20 static void AppendStringHeader(const std::string& header_name,
21 const std::string& header_value,
22 std::string* output) {
23 if (!header_value.empty()) {
24 *output += header_name + ": " + header_value + "\n";
28 // Appends the header name and the value to |output|, if the value is
29 // nonzero.
30 static void AppendUint32Header(const std::string& header_name,
31 uint32 header_value,
32 std::string* output) {
33 if (header_value != 0) {
34 *output += (header_name + ": " + base::StringPrintf("%u", header_value) +
35 "\n");
39 } // namespace
41 namespace dbus {
43 Message::Message()
44 : raw_message_(NULL) {
47 Message::~Message() {
48 if (raw_message_)
49 dbus_message_unref(raw_message_);
52 void Message::Init(DBusMessage* raw_message) {
53 DCHECK(!raw_message_);
54 raw_message_ = raw_message;
57 Message::MessageType Message::GetMessageType() {
58 if (!raw_message_)
59 return MESSAGE_INVALID;
60 const int type = dbus_message_get_type(raw_message_);
61 return static_cast<Message::MessageType>(type);
64 std::string Message::GetMessageTypeAsString() {
65 switch (GetMessageType()) {
66 case MESSAGE_INVALID:
67 return "MESSAGE_INVALID";
68 case MESSAGE_METHOD_CALL:
69 return "MESSAGE_METHOD_CALL";
70 case MESSAGE_METHOD_RETURN:
71 return "MESSAGE_METHOD_RETURN";
72 case MESSAGE_SIGNAL:
73 return "MESSAGE_SIGNAL";
74 case MESSAGE_ERROR:
75 return "MESSAGE_ERROR";
77 NOTREACHED();
78 return "";
81 std::string Message::ToStringInternal(const std::string& indent,
82 MessageReader* reader) {
83 const char* kBrokenMessage = "[broken message]";
84 std::string output;
85 while (reader->HasMoreData()) {
86 const DataType type = reader->GetDataType();
87 switch (type) {
88 case BYTE: {
89 uint8 value = 0;
90 if (!reader->PopByte(&value))
91 return kBrokenMessage;
92 output += indent + "byte " + base::StringPrintf("%d", value) + "\n";
93 break;
95 case BOOL: {
96 bool value = false;
97 if (!reader->PopBool(&value))
98 return kBrokenMessage;
99 output += indent + "bool " + (value ? "true" : "false") + "\n";
100 break;
102 case INT16: {
103 int16 value = 0;
104 if (!reader->PopInt16(&value))
105 return kBrokenMessage;
106 output += indent + "int16 " + base::StringPrintf("%d", value) + "\n";
107 break;
109 case UINT16: {
110 uint16 value = 0;
111 if (!reader->PopUint16(&value))
112 return kBrokenMessage;
113 output += indent + "uint16 " + base::StringPrintf("%d", value) + "\n";
114 break;
116 case INT32: {
117 int32 value = 0;
118 if (!reader->PopInt32(&value))
119 return kBrokenMessage;
120 output += indent + "int32 " + base::StringPrintf("%d", value) + "\n";
121 break;
123 case UINT32: {
124 uint32 value = 0;
125 if (!reader->PopUint32(&value))
126 return kBrokenMessage;
127 output += indent + "uint32 " + base::StringPrintf("%u", value) + "\n";
128 break;
130 case INT64: {
131 int64 value = 0;
132 if (!reader->PopInt64(&value))
133 return kBrokenMessage;
134 output += (indent + "int64 " +
135 base::StringPrintf("%" PRId64, value) + "\n");
136 break;
138 case UINT64: {
139 uint64 value = 0;
140 if (!reader->PopUint64(&value))
141 return kBrokenMessage;
142 output += (indent + "uint64 " +
143 base::StringPrintf("%" PRIu64, value) + "\n");
144 break;
146 case DOUBLE: {
147 double value = 0;
148 if (!reader->PopDouble(&value))
149 return kBrokenMessage;
150 output += indent + "double " + base::StringPrintf("%f", value) + "\n";
151 break;
153 case STRING: {
154 std::string value;
155 if (!reader->PopString(&value))
156 return kBrokenMessage;
157 output += indent + "string \"" + value + "\"\n";
158 break;
160 case OBJECT_PATH: {
161 ObjectPath value;
162 if (!reader->PopObjectPath(&value))
163 return kBrokenMessage;
164 output += indent + "object_path \"" + value.value() + "\"\n";
165 break;
167 case ARRAY: {
168 MessageReader sub_reader(this);
169 if (!reader->PopArray(&sub_reader))
170 return kBrokenMessage;
171 output += indent + "array [\n";
172 output += ToStringInternal(indent + " ", &sub_reader);
173 output += indent + "]\n";
174 break;
176 case STRUCT: {
177 MessageReader sub_reader(this);
178 if (!reader->PopStruct(&sub_reader))
179 return kBrokenMessage;
180 output += indent + "struct {\n";
181 output += ToStringInternal(indent + " ", &sub_reader);
182 output += indent + "}\n";
183 break;
185 case DICT_ENTRY: {
186 MessageReader sub_reader(this);
187 if (!reader->PopDictEntry(&sub_reader))
188 return kBrokenMessage;
189 output += indent + "dict entry {\n";
190 output += ToStringInternal(indent + " ", &sub_reader);
191 output += indent + "}\n";
192 break;
194 case VARIANT: {
195 MessageReader sub_reader(this);
196 if (!reader->PopVariant(&sub_reader))
197 return kBrokenMessage;
198 output += indent + "variant ";
199 output += ToStringInternal(indent + " ", &sub_reader);
200 break;
202 default:
203 LOG(FATAL) << "Unknown type: " << type;
206 return output;
209 // The returned string consists of message headers such as
210 // destination if any, followed by a blank line, and the message
211 // payload. For example, a MethodCall's ToString() will look like:
213 // destination: com.example.Service
214 // path: /com/example/Object
215 // interface: com.example.Interface
216 // member: SomeMethod
218 // string \"payload\"
219 // ...
220 std::string Message::ToString() {
221 if (!raw_message_)
222 return "";
224 // Generate headers first.
225 std::string headers;
226 AppendStringHeader("message_type", GetMessageTypeAsString(), &headers);
227 AppendStringHeader("destination", GetDestination(), &headers);
228 AppendStringHeader("path", GetPath().value(), &headers);
229 AppendStringHeader("interface", GetInterface(), &headers);
230 AppendStringHeader("member", GetMember(), &headers);
231 AppendStringHeader("error_name", GetErrorName(), &headers);
232 AppendStringHeader("sender", GetSender(), &headers);
233 AppendStringHeader("signature", GetSignature(), &headers);
234 AppendUint32Header("serial", GetSerial(), &headers);
235 AppendUint32Header("reply_serial", GetReplySerial(), &headers);
237 // Generate the payload.
238 MessageReader reader(this);
239 return headers + "\n" + ToStringInternal("", &reader);
242 void Message::SetDestination(const std::string& destination) {
243 const bool success = dbus_message_set_destination(raw_message_,
244 destination.c_str());
245 CHECK(success) << "Unable to allocate memory";
248 void Message::SetPath(const ObjectPath& path) {
249 const bool success = dbus_message_set_path(raw_message_,
250 path.value().c_str());
251 CHECK(success) << "Unable to allocate memory";
254 void Message::SetInterface(const std::string& interface) {
255 const bool success = dbus_message_set_interface(raw_message_,
256 interface.c_str());
257 CHECK(success) << "Unable to allocate memory";
260 void Message::SetMember(const std::string& member) {
261 const bool success = dbus_message_set_member(raw_message_,
262 member.c_str());
263 CHECK(success) << "Unable to allocate memory";
266 void Message::SetErrorName(const std::string& error_name) {
267 const bool success = dbus_message_set_error_name(raw_message_,
268 error_name.c_str());
269 CHECK(success) << "Unable to allocate memory";
272 void Message::SetSender(const std::string& sender) {
273 const bool success = dbus_message_set_sender(raw_message_,
274 sender.c_str());
275 CHECK(success) << "Unable to allocate memory";
278 void Message::SetSerial(uint32 serial) {
279 dbus_message_set_serial(raw_message_, serial);
282 void Message::SetReplySerial(uint32 reply_serial) {
283 dbus_message_set_reply_serial(raw_message_, reply_serial);
286 std::string Message::GetDestination() {
287 const char* destination = dbus_message_get_destination(raw_message_);
288 return destination ? destination : "";
291 ObjectPath Message::GetPath() {
292 const char* path = dbus_message_get_path(raw_message_);
293 return ObjectPath(path ? path : "");
296 std::string Message::GetInterface() {
297 const char* interface = dbus_message_get_interface(raw_message_);
298 return interface ? interface : "";
301 std::string Message::GetMember() {
302 const char* member = dbus_message_get_member(raw_message_);
303 return member ? member : "";
306 std::string Message::GetErrorName() {
307 const char* error_name = dbus_message_get_error_name(raw_message_);
308 return error_name ? error_name : "";
311 std::string Message::GetSender() {
312 const char* sender = dbus_message_get_sender(raw_message_);
313 return sender ? sender : "";
316 std::string Message::GetSignature() {
317 const char* signature = dbus_message_get_signature(raw_message_);
318 return signature ? signature : "";
321 uint32 Message::GetSerial() {
322 return dbus_message_get_serial(raw_message_);
325 uint32 Message::GetReplySerial() {
326 return dbus_message_get_reply_serial(raw_message_);
330 // MethodCall implementation.
333 MethodCall::MethodCall(const std::string& interface_name,
334 const std::string& method_name)
335 : Message() {
336 Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
338 SetInterface(interface_name);
339 SetMember(method_name);
342 MethodCall::MethodCall() : Message() {
345 MethodCall* MethodCall::FromRawMessage(DBusMessage* raw_message) {
346 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_CALL, dbus_message_get_type(raw_message));
348 MethodCall* method_call = new MethodCall;
349 method_call->Init(raw_message);
350 return method_call;
354 // Signal implementation.
356 Signal::Signal(const std::string& interface_name,
357 const std::string& method_name)
358 : Message() {
359 Init(dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL));
361 SetInterface(interface_name);
362 SetMember(method_name);
365 Signal::Signal() : Message() {
368 Signal* Signal::FromRawMessage(DBusMessage* raw_message) {
369 DCHECK_EQ(DBUS_MESSAGE_TYPE_SIGNAL, dbus_message_get_type(raw_message));
371 Signal* signal = new Signal;
372 signal->Init(raw_message);
373 return signal;
377 // Response implementation.
380 Response::Response() : Message() {
383 Response* Response::FromRawMessage(DBusMessage* raw_message) {
384 DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_RETURN,
385 dbus_message_get_type(raw_message));
387 Response* response = new Response;
388 response->Init(raw_message);
389 return response;
392 Response* Response::FromMethodCall(MethodCall* method_call) {
393 Response* response = new Response;
394 response->Init(dbus_message_new_method_return(method_call->raw_message()));
395 return response;
398 Response* Response::CreateEmpty() {
399 Response* response = new Response;
400 response->Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN));
401 return response;
404 // ErrorResponse implementation.
407 ErrorResponse::ErrorResponse() : Response() {
410 ErrorResponse* ErrorResponse::FromRawMessage(DBusMessage* raw_message) {
411 DCHECK_EQ(DBUS_MESSAGE_TYPE_ERROR, dbus_message_get_type(raw_message));
413 ErrorResponse* response = new ErrorResponse;
414 response->Init(raw_message);
415 return response;
418 ErrorResponse* ErrorResponse::FromMethodCall(
419 MethodCall* method_call,
420 const std::string& error_name,
421 const std::string& error_message) {
422 ErrorResponse* response = new ErrorResponse;
423 response->Init(dbus_message_new_error(method_call->raw_message(),
424 error_name.c_str(),
425 error_message.c_str()));
426 return response;
430 // MessageWriter implementation.
433 MessageWriter::MessageWriter(Message* message) :
434 message_(message),
435 container_is_open_(false) {
436 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
437 if (message)
438 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
441 MessageWriter::~MessageWriter() {
444 void MessageWriter::AppendByte(uint8 value) {
445 AppendBasic(DBUS_TYPE_BYTE, &value);
448 void MessageWriter::AppendBool(bool value) {
449 // The size of dbus_bool_t and the size of bool are different. The
450 // former is always 4 per dbus-types.h, whereas the latter is usually 1.
451 // dbus_message_iter_append_basic() used in AppendBasic() expects four
452 // bytes for DBUS_TYPE_BOOLEAN, so we must pass a dbus_bool_t, instead
453 // of a bool, to AppendBasic().
454 dbus_bool_t dbus_value = value;
455 AppendBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
458 void MessageWriter::AppendInt16(int16 value) {
459 AppendBasic(DBUS_TYPE_INT16, &value);
462 void MessageWriter::AppendUint16(uint16 value) {
463 AppendBasic(DBUS_TYPE_UINT16, &value);
466 void MessageWriter::AppendInt32(int32 value) {
467 AppendBasic(DBUS_TYPE_INT32, &value);
470 void MessageWriter::AppendUint32(uint32 value) {
471 AppendBasic(DBUS_TYPE_UINT32, &value);
474 void MessageWriter::AppendInt64(int64 value) {
475 AppendBasic(DBUS_TYPE_INT64, &value);
478 void MessageWriter::AppendUint64(uint64 value) {
479 AppendBasic(DBUS_TYPE_UINT64, &value);
482 void MessageWriter::AppendDouble(double value) {
483 AppendBasic(DBUS_TYPE_DOUBLE, &value);
486 void MessageWriter::AppendString(const std::string& value) {
487 const char* pointer = value.c_str();
488 AppendBasic(DBUS_TYPE_STRING, &pointer);
489 // TODO(satorux): It may make sense to return an error here, as the
490 // input string can be large. If needed, we could add something like
491 // bool AppendStringWithErrorChecking().
494 void MessageWriter::AppendObjectPath(const ObjectPath& value) {
495 const char* pointer = value.value().c_str();
496 AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
499 // Ideally, client shouldn't need to supply the signature string, but
500 // the underlying D-Bus library requires us to supply this before
501 // appending contents to array and variant. It's technically possible
502 // for us to design API that doesn't require the signature but it will
503 // complicate the implementation so we decided to have the signature
504 // parameter. Hopefully, variants are less used in request messages from
505 // client side than response message from server side, so this should
506 // not be a big issue.
507 void MessageWriter::OpenArray(const std::string& signature,
508 MessageWriter* writer) {
509 DCHECK(!container_is_open_);
511 const bool success = dbus_message_iter_open_container(
512 &raw_message_iter_,
513 DBUS_TYPE_ARRAY,
514 signature.c_str(),
515 &writer->raw_message_iter_);
516 CHECK(success) << "Unable to allocate memory";
517 container_is_open_ = true;
520 void MessageWriter::OpenVariant(const std::string& signature,
521 MessageWriter* writer) {
522 DCHECK(!container_is_open_);
524 const bool success = dbus_message_iter_open_container(
525 &raw_message_iter_,
526 DBUS_TYPE_VARIANT,
527 signature.c_str(),
528 &writer->raw_message_iter_);
529 CHECK(success) << "Unable to allocate memory";
530 container_is_open_ = true;
533 void MessageWriter::OpenStruct(MessageWriter* writer) {
534 DCHECK(!container_is_open_);
536 const bool success = dbus_message_iter_open_container(
537 &raw_message_iter_,
538 DBUS_TYPE_STRUCT,
539 NULL, // Signature should be NULL.
540 &writer->raw_message_iter_);
541 CHECK(success) << "Unable to allocate memory";
542 container_is_open_ = true;
545 void MessageWriter::OpenDictEntry(MessageWriter* writer) {
546 DCHECK(!container_is_open_);
548 const bool success = dbus_message_iter_open_container(
549 &raw_message_iter_,
550 DBUS_TYPE_DICT_ENTRY,
551 NULL, // Signature should be NULL.
552 &writer->raw_message_iter_);
553 CHECK(success) << "Unable to allocate memory";
554 container_is_open_ = true;
557 void MessageWriter::CloseContainer(MessageWriter* writer) {
558 DCHECK(container_is_open_);
560 const bool success = dbus_message_iter_close_container(
561 &raw_message_iter_, &writer->raw_message_iter_);
562 CHECK(success) << "Unable to allocate memory";
563 container_is_open_ = false;
566 void MessageWriter::AppendArrayOfBytes(const uint8* values, size_t length) {
567 DCHECK(!container_is_open_);
568 MessageWriter array_writer(message_);
569 OpenArray("y", &array_writer);
570 const bool success = dbus_message_iter_append_fixed_array(
571 &(array_writer.raw_message_iter_),
572 DBUS_TYPE_BYTE,
573 &values,
574 static_cast<int>(length));
575 CHECK(success) << "Unable to allocate memory";
576 CloseContainer(&array_writer);
579 void MessageWriter::AppendArrayOfStrings(
580 const std::vector<std::string>& strings) {
581 DCHECK(!container_is_open_);
582 MessageWriter array_writer(message_);
583 OpenArray("s", &array_writer);
584 for (size_t i = 0; i < strings.size(); ++i) {
585 array_writer.AppendString(strings[i]);
587 CloseContainer(&array_writer);
590 void MessageWriter::AppendArrayOfObjectPaths(
591 const std::vector<ObjectPath>& object_paths) {
592 DCHECK(!container_is_open_);
593 MessageWriter array_writer(message_);
594 OpenArray("o", &array_writer);
595 for (size_t i = 0; i < object_paths.size(); ++i) {
596 array_writer.AppendObjectPath(object_paths[i]);
598 CloseContainer(&array_writer);
601 bool MessageWriter::AppendProtoAsArrayOfBytes(
602 const google::protobuf::MessageLite& protobuf) {
603 std::string serialized_proto;
604 if (!protobuf.SerializeToString(&serialized_proto)) {
605 LOG(ERROR) << "Unable to serialize supplied protocol buffer";
606 return false;
608 AppendArrayOfBytes(reinterpret_cast<const uint8*>(serialized_proto.data()),
609 serialized_proto.size());
610 return true;
613 void MessageWriter::AppendVariantOfByte(uint8 value) {
614 AppendVariantOfBasic(DBUS_TYPE_BYTE, &value);
617 void MessageWriter::AppendVariantOfBool(bool value) {
618 // See the comment at MessageWriter::AppendBool().
619 dbus_bool_t dbus_value = value;
620 AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
623 void MessageWriter::AppendVariantOfInt16(int16 value) {
624 AppendVariantOfBasic(DBUS_TYPE_INT16, &value);
627 void MessageWriter::AppendVariantOfUint16(uint16 value) {
628 AppendVariantOfBasic(DBUS_TYPE_UINT16, &value);
631 void MessageWriter::AppendVariantOfInt32(int32 value) {
632 AppendVariantOfBasic(DBUS_TYPE_INT32, &value);
635 void MessageWriter::AppendVariantOfUint32(uint32 value) {
636 AppendVariantOfBasic(DBUS_TYPE_UINT32, &value);
639 void MessageWriter::AppendVariantOfInt64(int64 value) {
640 AppendVariantOfBasic(DBUS_TYPE_INT64, &value);
643 void MessageWriter::AppendVariantOfUint64(uint64 value) {
644 AppendVariantOfBasic(DBUS_TYPE_UINT64, &value);
647 void MessageWriter::AppendVariantOfDouble(double value) {
648 AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value);
651 void MessageWriter::AppendVariantOfString(const std::string& value) {
652 const char* pointer = value.c_str();
653 AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer);
656 void MessageWriter::AppendVariantOfObjectPath(const ObjectPath& value) {
657 const char* pointer = value.value().c_str();
658 AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
661 void MessageWriter::AppendBasic(int dbus_type, const void* value) {
662 DCHECK(!container_is_open_);
664 const bool success = dbus_message_iter_append_basic(
665 &raw_message_iter_, dbus_type, value);
666 // dbus_message_iter_append_basic() fails only when there is not enough
667 // memory. We don't return this error as there is nothing we can do when
668 // it fails to allocate memory for a byte etc.
669 CHECK(success) << "Unable to allocate memory";
672 void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) {
673 const std::string signature = base::StringPrintf("%c", dbus_type);
674 MessageWriter variant_writer(message_);
675 OpenVariant(signature, &variant_writer);
676 variant_writer.AppendBasic(dbus_type, value);
677 CloseContainer(&variant_writer);
681 // MessageReader implementation.
684 MessageReader::MessageReader(Message* message)
685 : message_(message) {
686 memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
687 if (message)
688 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
692 MessageReader::~MessageReader() {
695 bool MessageReader::HasMoreData() {
696 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
697 return dbus_type != DBUS_TYPE_INVALID;
700 bool MessageReader::PopByte(uint8* value) {
701 return PopBasic(DBUS_TYPE_BYTE, value);
704 bool MessageReader::PopBool(bool* value) {
705 // Like MessageWriter::AppendBool(), we should copy |value| to
706 // dbus_bool_t, as dbus_message_iter_get_basic() used in PopBasic()
707 // expects four bytes for DBUS_TYPE_BOOLEAN.
708 dbus_bool_t dbus_value = FALSE;
709 const bool success = PopBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
710 *value = static_cast<bool>(dbus_value);
711 return success;
714 bool MessageReader::PopInt16(int16* value) {
715 return PopBasic(DBUS_TYPE_INT16, value);
718 bool MessageReader::PopUint16(uint16* value) {
719 return PopBasic(DBUS_TYPE_UINT16, value);
722 bool MessageReader::PopInt32(int32* value) {
723 return PopBasic(DBUS_TYPE_INT32, value);
726 bool MessageReader::PopUint32(uint32* value) {
727 return PopBasic(DBUS_TYPE_UINT32, value);
730 bool MessageReader::PopInt64(int64* value) {
731 return PopBasic(DBUS_TYPE_INT64, value);
734 bool MessageReader::PopUint64(uint64* value) {
735 return PopBasic(DBUS_TYPE_UINT64, value);
738 bool MessageReader::PopDouble(double* value) {
739 return PopBasic(DBUS_TYPE_DOUBLE, value);
742 bool MessageReader::PopString(std::string* value) {
743 char* tmp_value = NULL;
744 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
745 if (success)
746 value->assign(tmp_value);
747 return success;
750 bool MessageReader::PopObjectPath(ObjectPath* value) {
751 char* tmp_value = NULL;
752 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
753 if (success)
754 *value = ObjectPath(tmp_value);
755 return success;
758 bool MessageReader::PopArray(MessageReader* sub_reader) {
759 return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
762 bool MessageReader::PopStruct(MessageReader* sub_reader) {
763 return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
766 bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
767 return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
770 bool MessageReader::PopVariant(MessageReader* sub_reader) {
771 return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
774 bool MessageReader::PopArrayOfBytes(uint8** bytes, size_t* length) {
775 MessageReader array_reader(message_);
776 if (!PopArray(&array_reader))
777 return false;
778 // An empty array is allowed.
779 if (!array_reader.HasMoreData()) {
780 *length = 0;
781 *bytes = NULL;
782 return true;
784 if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
785 return false;
786 int int_length = 0;
787 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
788 bytes,
789 &int_length);
790 *length = static_cast<int>(int_length);
791 return true;
794 bool MessageReader::PopArrayOfStrings(
795 std::vector<std::string> *strings) {
796 MessageReader array_reader(message_);
797 if (!PopArray(&array_reader))
798 return false;
799 while (array_reader.HasMoreData()) {
800 std::string string;
801 if (!array_reader.PopString(&string))
802 return false;
803 strings->push_back(string);
805 return true;
808 bool MessageReader::PopArrayOfObjectPaths(
809 std::vector<ObjectPath> *object_paths) {
810 MessageReader array_reader(message_);
811 if (!PopArray(&array_reader))
812 return false;
813 while (array_reader.HasMoreData()) {
814 ObjectPath object_path;
815 if (!array_reader.PopObjectPath(&object_path))
816 return false;
817 object_paths->push_back(object_path);
819 return true;
822 bool MessageReader::PopArrayOfBytesAsProto(
823 google::protobuf::MessageLite* protobuf) {
824 DCHECK(protobuf != NULL);
825 char* serialized_buf = NULL;
826 size_t buf_size = 0;
827 if (!PopArrayOfBytes(reinterpret_cast<uint8**>(&serialized_buf), &buf_size)) {
828 LOG(ERROR) << "Error reading array of bytes";
829 return false;
831 if (!protobuf->ParseFromArray(serialized_buf, buf_size)) {
832 LOG(ERROR) << "Failed to parse protocol buffer from array";
833 return false;
835 return true;
838 bool MessageReader::PopVariantOfByte(uint8* value) {
839 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
842 bool MessageReader::PopVariantOfBool(bool* value) {
843 // See the comment at MessageReader::PopBool().
844 dbus_bool_t dbus_value = FALSE;
845 const bool success = PopVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
846 *value = static_cast<bool>(dbus_value);
847 return success;
850 bool MessageReader::PopVariantOfInt16(int16* value) {
851 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
854 bool MessageReader::PopVariantOfUint16(uint16* value) {
855 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
858 bool MessageReader::PopVariantOfInt32(int32* value) {
859 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
862 bool MessageReader::PopVariantOfUint32(uint32* value) {
863 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
866 bool MessageReader::PopVariantOfInt64(int64* value) {
867 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
870 bool MessageReader::PopVariantOfUint64(uint64* value) {
871 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
874 bool MessageReader::PopVariantOfDouble(double* value) {
875 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
878 bool MessageReader::PopVariantOfString(std::string* value) {
879 char* tmp_value = NULL;
880 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
881 if (success)
882 value->assign(tmp_value);
883 return success;
886 bool MessageReader::PopVariantOfObjectPath(ObjectPath* value) {
887 char* tmp_value = NULL;
888 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
889 if (success)
890 *value = ObjectPath(tmp_value);
891 return success;
894 Message::DataType MessageReader::GetDataType() {
895 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
896 return static_cast<Message::DataType>(dbus_type);
899 bool MessageReader::CheckDataType(int dbus_type) {
900 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
901 if (actual_type != dbus_type) {
902 VLOG(1) << "Type " << dbus_type << " is expected but got "
903 << actual_type;
904 return false;
906 return true;
909 bool MessageReader::PopBasic(int dbus_type, void* value) {
910 if (!CheckDataType(dbus_type))
911 return false;
912 // dbus_message_iter_get_basic() here should always work, as we have
913 // already checked the next item's data type in CheckDataType(). Note
914 // that dbus_message_iter_get_basic() is a void function.
915 dbus_message_iter_get_basic(&raw_message_iter_, value);
916 DCHECK(value);
917 dbus_message_iter_next(&raw_message_iter_);
918 return true;
921 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
922 DCHECK_NE(this, sub_reader);
924 if (!CheckDataType(dbus_type))
925 return false;
926 dbus_message_iter_recurse(&raw_message_iter_,
927 &sub_reader->raw_message_iter_);
928 dbus_message_iter_next(&raw_message_iter_);
929 return true;
932 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
933 dbus::MessageReader variant_reader(message_);
934 if (!PopVariant(&variant_reader))
935 return false;
936 return variant_reader.PopBasic(dbus_type, value);
939 } // namespace dbus