1// Copyright (c) 2010, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29// 30// map_serializers_inl.h: implementation for serializing std::map and its 31// wrapper classes. 32// 33// See map_serializers.h for documentation. 34// 35// Author: Siyang Xie (lambxsy@google.com) 36 37#ifndef PROCESSOR_MAP_SERIALIZERS_INL_H__ 38#define PROCESSOR_MAP_SERIALIZERS_INL_H__ 39 40#include <map> 41#include <string> 42 43#include "processor/map_serializers.h" 44#include "processor/simple_serializer.h" 45 46#include "processor/address_map-inl.h" 47#include "processor/range_map-inl.h" 48#include "processor/contained_range_map-inl.h" 49 50#include "processor/logging.h" 51 52namespace google_breakpad { 53 54template<typename Key, typename Value> 55size_t StdMapSerializer<Key, Value>::SizeOf( 56 const std::map<Key, Value> &m) const { 57 size_t size = 0; 58 size_t header_size = (1 + m.size()) * sizeof(uint32_t); 59 size += header_size; 60 61 typename std::map<Key, Value>::const_iterator iter; 62 for (iter = m.begin(); iter != m.end(); ++iter) { 63 size += key_serializer_.SizeOf(iter->first); 64 size += value_serializer_.SizeOf(iter->second); 65 } 66 return size; 67} 68 69template<typename Key, typename Value> 70char *StdMapSerializer<Key, Value>::Write(const std::map<Key, Value> &m, 71 char *dest) const { 72 if (!dest) { 73 BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; 74 return NULL; 75 } 76 char *start_address = dest; 77 78 // Write header: 79 // Number of nodes. 80 dest = SimpleSerializer<uint32_t>::Write(m.size(), dest); 81 // Nodes offsets. 82 uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); 83 dest += sizeof(uint32_t) * m.size(); 84 85 char *key_address = dest; 86 dest += sizeof(Key) * m.size(); 87 88 // Traverse map. 89 typename std::map<Key, Value>::const_iterator iter; 90 int index = 0; 91 for (iter = m.begin(); iter != m.end(); ++iter, ++index) { 92 offsets[index] = static_cast<uint32_t>(dest - start_address); 93 key_address = key_serializer_.Write(iter->first, key_address); 94 dest = value_serializer_.Write(iter->second, dest); 95 } 96 return dest; 97} 98 99template<typename Key, typename Value> 100char *StdMapSerializer<Key, Value>::Serialize( 101 const std::map<Key, Value> &m, unsigned int *size) const { 102 // Compute size of memory to be allocated. 103 unsigned int size_to_alloc = SizeOf(m); 104 // Allocate memory. 105 char *serialized_data = new char[size_to_alloc]; 106 if (!serialized_data) { 107 BPLOG(INFO) << "StdMapSerializer memory allocation failed."; 108 if (size) *size = 0; 109 return NULL; 110 } 111 // Write serialized data into memory. 112 Write(m, serialized_data); 113 114 if (size) *size = size_to_alloc; 115 return serialized_data; 116} 117 118template<typename Address, typename Entry> 119size_t RangeMapSerializer<Address, Entry>::SizeOf( 120 const RangeMap<Address, Entry> &m) const { 121 size_t size = 0; 122 size_t header_size = (1 + m.map_.size()) * sizeof(uint32_t); 123 size += header_size; 124 125 typename std::map<Address, Range>::const_iterator iter; 126 for (iter = m.map_.begin(); iter != m.map_.end(); ++iter) { 127 // Size of key (high address). 128 size += address_serializer_.SizeOf(iter->first); 129 // Size of base (low address). 130 size += address_serializer_.SizeOf(iter->second.base()); 131 // Size of entry. 132 size += entry_serializer_.SizeOf(iter->second.entry()); 133 } 134 return size; 135} 136 137template<typename Address, typename Entry> 138char *RangeMapSerializer<Address, Entry>::Write( 139 const RangeMap<Address, Entry> &m, char *dest) const { 140 if (!dest) { 141 BPLOG(ERROR) << "RangeMapSerializer failed: write to NULL address."; 142 return NULL; 143 } 144 char *start_address = dest; 145 146 // Write header: 147 // Number of nodes. 148 dest = SimpleSerializer<uint32_t>::Write(m.map_.size(), dest); 149 // Nodes offsets. 150 uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); 151 dest += sizeof(uint32_t) * m.map_.size(); 152 153 char *key_address = dest; 154 dest += sizeof(Address) * m.map_.size(); 155 156 // Traverse map. 157 typename std::map<Address, Range>::const_iterator iter; 158 int index = 0; 159 for (iter = m.map_.begin(); iter != m.map_.end(); ++iter, ++index) { 160 offsets[index] = static_cast<uint32_t>(dest - start_address); 161 key_address = address_serializer_.Write(iter->first, key_address); 162 dest = address_serializer_.Write(iter->second.base(), dest); 163 dest = entry_serializer_.Write(iter->second.entry(), dest); 164 } 165 return dest; 166} 167 168template<typename Address, typename Entry> 169char *RangeMapSerializer<Address, Entry>::Serialize( 170 const RangeMap<Address, Entry> &m, unsigned int *size) const { 171 // Compute size of memory to be allocated. 172 unsigned int size_to_alloc = SizeOf(m); 173 // Allocate memory. 174 char *serialized_data = new char[size_to_alloc]; 175 if (!serialized_data) { 176 BPLOG(INFO) << "RangeMapSerializer memory allocation failed."; 177 if (size) *size = 0; 178 return NULL; 179 } 180 181 // Write serialized data into memory. 182 Write(m, serialized_data); 183 184 if (size) *size = size_to_alloc; 185 return serialized_data; 186} 187 188 189template<class AddrType, class EntryType> 190size_t ContainedRangeMapSerializer<AddrType, EntryType>::SizeOf( 191 const ContainedRangeMap<AddrType, EntryType> *m) const { 192 size_t size = 0; 193 size_t header_size = addr_serializer_.SizeOf(m->base_) 194 + entry_serializer_.SizeOf(m->entry_) 195 + sizeof(uint32_t); 196 size += header_size; 197 // In case m.map_ == NULL, we treat it as an empty map: 198 size += sizeof(uint32_t); 199 if (m->map_) { 200 size += m->map_->size() * sizeof(uint32_t); 201 typename Map::const_iterator iter; 202 for (iter = m->map_->begin(); iter != m->map_->end(); ++iter) { 203 size += addr_serializer_.SizeOf(iter->first); 204 // Recursive calculation of size: 205 size += SizeOf(iter->second); 206 } 207 } 208 return size; 209} 210 211template<class AddrType, class EntryType> 212char *ContainedRangeMapSerializer<AddrType, EntryType>::Write( 213 const ContainedRangeMap<AddrType, EntryType> *m, char *dest) const { 214 if (!dest) { 215 BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; 216 return NULL; 217 } 218 dest = addr_serializer_.Write(m->base_, dest); 219 dest = SimpleSerializer<uint32_t>::Write(entry_serializer_.SizeOf(m->entry_), 220 dest); 221 dest = entry_serializer_.Write(m->entry_, dest); 222 223 // Write map<<AddrType, ContainedRangeMap*>: 224 char *map_address = dest; 225 if (m->map_ == NULL) { 226 dest = SimpleSerializer<uint32_t>::Write(0, dest); 227 } else { 228 dest = SimpleSerializer<uint32_t>::Write(m->map_->size(), dest); 229 uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); 230 dest += sizeof(uint32_t) * m->map_->size(); 231 232 char *key_address = dest; 233 dest += sizeof(AddrType) * m->map_->size(); 234 235 // Traverse map. 236 typename Map::const_iterator iter; 237 int index = 0; 238 for (iter = m->map_->begin(); iter != m->map_->end(); ++iter, ++index) { 239 offsets[index] = static_cast<uint32_t>(dest - map_address); 240 key_address = addr_serializer_.Write(iter->first, key_address); 241 // Recursively write. 242 dest = Write(iter->second, dest); 243 } 244 } 245 return dest; 246} 247 248template<class AddrType, class EntryType> 249char *ContainedRangeMapSerializer<AddrType, EntryType>::Serialize( 250 const ContainedRangeMap<AddrType, EntryType> *m, unsigned int *size) const { 251 unsigned int size_to_alloc = SizeOf(m); 252 // Allocating memory. 253 char *serialized_data = new char[size_to_alloc]; 254 if (!serialized_data) { 255 BPLOG(INFO) << "ContainedRangeMapSerializer memory allocation failed."; 256 if (size) *size = 0; 257 return NULL; 258 } 259 Write(m, serialized_data); 260 if (size) *size = size_to_alloc; 261 return serialized_data; 262} 263 264} // namespace google_breakpad 265 266#endif // PROCESSOR_MAP_SERIALIZERS_INL_H__ 267