1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "minidump/minidump_simple_string_dictionary_writer.h"
16
17 #include <utility>
18
19 #include "base/logging.h"
20 #include "util/file/file_writer.h"
21 #include "util/numeric/safe_assignment.h"
22
23 namespace crashpad {
24
25 MinidumpSimpleStringDictionaryEntryWriter::
MinidumpSimpleStringDictionaryEntryWriter()26 MinidumpSimpleStringDictionaryEntryWriter()
27 : MinidumpWritable(), entry_(), key_(), value_() {
28 }
29
30 MinidumpSimpleStringDictionaryEntryWriter::
~MinidumpSimpleStringDictionaryEntryWriter()31 ~MinidumpSimpleStringDictionaryEntryWriter() {
32 }
33
34 const MinidumpSimpleStringDictionaryEntry*
35 MinidumpSimpleStringDictionaryEntryWriter::
GetMinidumpSimpleStringDictionaryEntry() const36 GetMinidumpSimpleStringDictionaryEntry() const {
37 DCHECK_EQ(state(), kStateWritable);
38
39 return &entry_;
40 }
41
SetKeyValue(const std::string & key,const std::string & value)42 void MinidumpSimpleStringDictionaryEntryWriter::SetKeyValue(
43 const std::string& key,
44 const std::string& value) {
45 DCHECK_EQ(state(), kStateMutable);
46
47 key_.SetUTF8(key);
48 value_.SetUTF8(value);
49 }
50
Freeze()51 bool MinidumpSimpleStringDictionaryEntryWriter::Freeze() {
52 DCHECK_EQ(state(), kStateMutable);
53
54 if (!MinidumpWritable::Freeze()) {
55 return false;
56 }
57
58 key_.RegisterRVA(&entry_.key);
59 value_.RegisterRVA(&entry_.value);
60
61 return true;
62 }
63
SizeOfObject()64 size_t MinidumpSimpleStringDictionaryEntryWriter::SizeOfObject() {
65 DCHECK_GE(state(), kStateFrozen);
66
67 // This object doesn’t directly write anything itself. Its
68 // MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
69 // MinidumpSimpleStringDictionary, and its children are responsible for
70 // writing themselves.
71 return 0;
72 }
73
74 std::vector<internal::MinidumpWritable*>
Children()75 MinidumpSimpleStringDictionaryEntryWriter::Children() {
76 DCHECK_GE(state(), kStateFrozen);
77
78 std::vector<MinidumpWritable*> children(1, &key_);
79 children.push_back(&value_);
80 return children;
81 }
82
WriteObject(FileWriterInterface * file_writer)83 bool MinidumpSimpleStringDictionaryEntryWriter::WriteObject(
84 FileWriterInterface* file_writer) {
85 DCHECK_EQ(state(), kStateWritable);
86
87 // This object doesn’t directly write anything itself. Its
88 // MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
89 // MinidumpSimpleStringDictionary, and its children are responsible for
90 // writing themselves.
91 return true;
92 }
93
MinidumpSimpleStringDictionaryWriter()94 MinidumpSimpleStringDictionaryWriter::MinidumpSimpleStringDictionaryWriter()
95 : MinidumpWritable(),
96 entries_(),
97 simple_string_dictionary_base_(new MinidumpSimpleStringDictionary()) {
98 }
99
~MinidumpSimpleStringDictionaryWriter()100 MinidumpSimpleStringDictionaryWriter::~MinidumpSimpleStringDictionaryWriter() {
101 for (auto& item : entries_)
102 delete item.second;
103 }
104
InitializeFromMap(const std::map<std::string,std::string> & map)105 void MinidumpSimpleStringDictionaryWriter::InitializeFromMap(
106 const std::map<std::string, std::string>& map) {
107 DCHECK_EQ(state(), kStateMutable);
108 DCHECK(entries_.empty());
109
110 for (const auto& iterator : map) {
111 auto entry = std::make_unique<MinidumpSimpleStringDictionaryEntryWriter>();
112 entry->SetKeyValue(iterator.first, iterator.second);
113 AddEntry(std::move(entry));
114 }
115 }
116
AddEntry(std::unique_ptr<MinidumpSimpleStringDictionaryEntryWriter> entry)117 void MinidumpSimpleStringDictionaryWriter::AddEntry(
118 std::unique_ptr<MinidumpSimpleStringDictionaryEntryWriter> entry) {
119 DCHECK_EQ(state(), kStateMutable);
120
121 const std::string& key = entry->Key();
122 auto iterator = entries_.find(key);
123 if (iterator != entries_.end()) {
124 delete iterator->second;
125 iterator->second = entry.release();
126 } else {
127 entries_[key] = entry.release();
128 }
129 }
130
IsUseful() const131 bool MinidumpSimpleStringDictionaryWriter::IsUseful() const {
132 return !entries_.empty();
133 }
134
Freeze()135 bool MinidumpSimpleStringDictionaryWriter::Freeze() {
136 DCHECK_EQ(state(), kStateMutable);
137
138 if (!MinidumpWritable::Freeze()) {
139 return false;
140 }
141
142 size_t entry_count = entries_.size();
143 if (!AssignIfInRange(&simple_string_dictionary_base_->count, entry_count)) {
144 LOG(ERROR) << "entry_count " << entry_count << " out of range";
145 return false;
146 }
147
148 return true;
149 }
150
SizeOfObject()151 size_t MinidumpSimpleStringDictionaryWriter::SizeOfObject() {
152 DCHECK_GE(state(), kStateFrozen);
153
154 return sizeof(*simple_string_dictionary_base_) +
155 entries_.size() * sizeof(MinidumpSimpleStringDictionaryEntry);
156 }
157
158 std::vector<internal::MinidumpWritable*>
Children()159 MinidumpSimpleStringDictionaryWriter::Children() {
160 DCHECK_GE(state(), kStateMutable);
161
162 std::vector<MinidumpWritable*> children;
163 for (const auto& key_entry : entries_) {
164 children.push_back(key_entry.second);
165 }
166
167 return children;
168 }
169
WriteObject(FileWriterInterface * file_writer)170 bool MinidumpSimpleStringDictionaryWriter::WriteObject(
171 FileWriterInterface* file_writer) {
172 DCHECK_GE(state(), kStateWritable);
173
174 WritableIoVec iov;
175 iov.iov_base = simple_string_dictionary_base_.get();
176 iov.iov_len = sizeof(*simple_string_dictionary_base_);
177 std::vector<WritableIoVec> iovecs(1, iov);
178
179 for (const auto& key_entry : entries_) {
180 iov.iov_base = key_entry.second->GetMinidumpSimpleStringDictionaryEntry();
181 iov.iov_len = sizeof(MinidumpSimpleStringDictionaryEntry);
182 iovecs.push_back(iov);
183 }
184
185 return file_writer->WriteIoVec(&iovecs);
186 }
187
188 } // namespace crashpad
189