FormattersContainer.h revision 309124
1//===-- FormattersContainer.h -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef lldb_FormattersContainer_h_ 11#define lldb_FormattersContainer_h_ 12 13// C Includes 14// C++ Includes 15#include <functional> 16#include <map> 17#include <memory> 18#include <mutex> 19#include <string> 20 21// Other libraries and framework includes 22// Project includes 23#include "lldb/lldb-public.h" 24 25#include "lldb/Core/RegularExpression.h" 26#include "lldb/Core/ValueObject.h" 27#include "lldb/DataFormatters/FormatClasses.h" 28#include "lldb/DataFormatters/TypeFormat.h" 29#include "lldb/DataFormatters/TypeSummary.h" 30#include "lldb/DataFormatters/TypeSynthetic.h" 31#include "lldb/DataFormatters/TypeValidator.h" 32#include "lldb/Symbol/CompilerType.h" 33#include "lldb/Utility/StringLexer.h" 34 35namespace lldb_private { 36 37class IFormatChangeListener 38{ 39public: 40 virtual 41 ~IFormatChangeListener() = default; 42 43 virtual void 44 Changed () = 0; 45 46 virtual uint32_t 47 GetCurrentRevision () = 0; 48}; 49 50// if the user tries to add formatters for, say, "struct Foo" 51// those will not match any type because of the way we strip qualifiers from typenames 52// this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo 53// and strips the unnecessary qualifier 54static inline ConstString 55GetValidTypeName_Impl (const ConstString& type) 56{ 57 if (type.IsEmpty()) 58 return type; 59 60 std::string type_cstr(type.AsCString()); 61 lldb_utility::StringLexer type_lexer(type_cstr); 62 63 type_lexer.AdvanceIf("class "); 64 type_lexer.AdvanceIf("enum "); 65 type_lexer.AdvanceIf("struct "); 66 type_lexer.AdvanceIf("union "); 67 68 while (type_lexer.NextIf({' ','\t','\v','\f'}).first) 69 ; 70 71 return ConstString(type_lexer.GetUnlexed()); 72} 73 74template<typename KeyType, typename ValueType> 75class FormattersContainer; 76 77template<typename KeyType, typename ValueType> 78class FormatMap 79{ 80public: 81 typedef typename ValueType::SharedPointer ValueSP; 82 typedef std::map<KeyType, ValueSP> MapType; 83 typedef typename MapType::iterator MapIterator; 84 typedef std::function<bool(KeyType, const ValueSP&)> ForEachCallback; 85 86 FormatMap(IFormatChangeListener *lst) : m_map(), m_map_mutex(), listener(lst) {} 87 88 void 89 Add(KeyType name, const ValueSP &entry) 90 { 91 if (listener) 92 entry->GetRevision() = listener->GetCurrentRevision(); 93 else 94 entry->GetRevision() = 0; 95 96 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 97 m_map[name] = entry; 98 if (listener) 99 listener->Changed(); 100 } 101 102 bool 103 Delete(KeyType name) 104 { 105 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 106 MapIterator iter = m_map.find(name); 107 if (iter == m_map.end()) 108 return false; 109 m_map.erase(name); 110 if (listener) 111 listener->Changed(); 112 return true; 113 } 114 115 void 116 Clear() 117 { 118 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 119 m_map.clear(); 120 if (listener) 121 listener->Changed(); 122 } 123 124 bool 125 Get(KeyType name, ValueSP &entry) 126 { 127 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 128 MapIterator iter = m_map.find(name); 129 if (iter == m_map.end()) 130 return false; 131 entry = iter->second; 132 return true; 133 } 134 135 void 136 ForEach(ForEachCallback callback) 137 { 138 if (callback) 139 { 140 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 141 MapIterator pos, end = m_map.end(); 142 for (pos = m_map.begin(); pos != end; pos++) 143 { 144 KeyType type = pos->first; 145 if (!callback(type, pos->second)) 146 break; 147 } 148 } 149 } 150 151 uint32_t 152 GetCount () 153 { 154 return m_map.size(); 155 } 156 157 ValueSP 158 GetValueAtIndex(size_t index) 159 { 160 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 161 MapIterator iter = m_map.begin(); 162 MapIterator end = m_map.end(); 163 while (index > 0) 164 { 165 iter++; 166 index--; 167 if (end == iter) 168 return ValueSP(); 169 } 170 return iter->second; 171 } 172 173 KeyType 174 GetKeyAtIndex(size_t index) 175 { 176 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 177 MapIterator iter = m_map.begin(); 178 MapIterator end = m_map.end(); 179 while (index > 0) 180 { 181 iter++; 182 index--; 183 if (end == iter) 184 return KeyType(); 185 } 186 return iter->first; 187 } 188 189protected: 190 MapType m_map; 191 std::recursive_mutex m_map_mutex; 192 IFormatChangeListener* listener; 193 194 MapType& 195 map () 196 { 197 return m_map; 198 } 199 200 std::recursive_mutex & 201 mutex() 202 { 203 return m_map_mutex; 204 } 205 206 friend class FormattersContainer<KeyType, ValueType>; 207 friend class FormatManager; 208}; 209 210template<typename KeyType, typename ValueType> 211class FormattersContainer 212{ 213protected: 214 typedef FormatMap<KeyType,ValueType> BackEndType; 215 216public: 217 typedef typename BackEndType::MapType MapType; 218 typedef typename MapType::iterator MapIterator; 219 typedef typename MapType::key_type MapKeyType; 220 typedef typename MapType::mapped_type MapValueType; 221 typedef typename BackEndType::ForEachCallback ForEachCallback; 222 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer; 223 224 friend class TypeCategoryImpl; 225 226 FormattersContainer(std::string name, 227 IFormatChangeListener* lst) : 228 m_format_map(lst), 229 m_name(name) 230 { 231 } 232 233 void 234 Add (const MapKeyType &type, const MapValueType& entry) 235 { 236 Add_Impl(type, entry, static_cast<KeyType*>(nullptr)); 237 } 238 239 bool 240 Delete (ConstString type) 241 { 242 return Delete_Impl(type, static_cast<KeyType*>(nullptr)); 243 } 244 245 bool 246 Get(ValueObject& valobj, 247 MapValueType& entry, 248 lldb::DynamicValueType use_dynamic, 249 uint32_t* why = nullptr) 250 { 251 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; 252 CompilerType ast_type(valobj.GetCompilerType()); 253 bool ret = Get(valobj, ast_type, entry, use_dynamic, value); 254 if (ret) 255 entry = MapValueType(entry); 256 else 257 entry = MapValueType(); 258 if (why) 259 *why = value; 260 return ret; 261 } 262 263 bool 264 Get (ConstString type, MapValueType& entry) 265 { 266 return Get_Impl(type, entry, static_cast<KeyType*>(nullptr)); 267 } 268 269 bool 270 GetExact (ConstString type, MapValueType& entry) 271 { 272 return GetExact_Impl(type, entry, static_cast<KeyType*>(nullptr)); 273 } 274 275 MapValueType 276 GetAtIndex (size_t index) 277 { 278 return m_format_map.GetValueAtIndex(index); 279 } 280 281 lldb::TypeNameSpecifierImplSP 282 GetTypeNameSpecifierAtIndex (size_t index) 283 { 284 return GetTypeNameSpecifierAtIndex_Impl(index, static_cast<KeyType*>(nullptr)); 285 } 286 287 void 288 Clear () 289 { 290 m_format_map.Clear(); 291 } 292 293 void 294 ForEach (ForEachCallback callback) 295 { 296 m_format_map.ForEach(callback); 297 } 298 299 uint32_t 300 GetCount () 301 { 302 return m_format_map.GetCount(); 303 } 304 305protected: 306 BackEndType m_format_map; 307 std::string m_name; 308 309 DISALLOW_COPY_AND_ASSIGN(FormattersContainer); 310 311 void 312 Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy) 313 { 314 m_format_map.Add(type,entry); 315 } 316 317 void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy) 318 { 319 m_format_map.Add(GetValidTypeName_Impl(type), entry); 320 } 321 322 bool 323 Delete_Impl (ConstString type, ConstString *dummy) 324 { 325 return m_format_map.Delete(type); 326 } 327 328 bool 329 Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) 330 { 331 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 332 MapIterator pos, end = m_format_map.map().end(); 333 for (pos = m_format_map.map().begin(); pos != end; pos++) 334 { 335 lldb::RegularExpressionSP regex = pos->first; 336 if (::strcmp(type.AsCString(), regex->GetText()) == 0) 337 { 338 m_format_map.map().erase(pos); 339 if (m_format_map.listener) 340 m_format_map.listener->Changed(); 341 return true; 342 } 343 } 344 return false; 345 } 346 347 bool 348 Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy) 349 { 350 return m_format_map.Get(type, entry); 351 } 352 353 bool 354 GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy) 355 { 356 return Get_Impl(type, entry, static_cast<KeyType*>(nullptr)); 357 } 358 359 lldb::TypeNameSpecifierImplSP 360 GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy) 361 { 362 ConstString key = m_format_map.GetKeyAtIndex(index); 363 if (key) 364 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(), 365 false)); 366 else 367 return lldb::TypeNameSpecifierImplSP(); 368 } 369 370 lldb::TypeNameSpecifierImplSP 371 GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy) 372 { 373 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); 374 if (regex.get() == nullptr) 375 return lldb::TypeNameSpecifierImplSP(); 376 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(), 377 true)); 378 } 379 380 bool 381 Get_Impl(ConstString key, MapValueType &value, lldb::RegularExpressionSP *dummy) 382 { 383 const char *key_cstr = key.AsCString(); 384 if (!key_cstr) 385 return false; 386 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 387 MapIterator pos, end = m_format_map.map().end(); 388 for (pos = m_format_map.map().begin(); pos != end; pos++) 389 { 390 lldb::RegularExpressionSP regex = pos->first; 391 if (regex->Execute(key_cstr)) 392 { 393 value = pos->second; 394 return true; 395 } 396 } 397 return false; 398 } 399 400 bool 401 GetExact_Impl(ConstString key, MapValueType &value, lldb::RegularExpressionSP *dummy) 402 { 403 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 404 MapIterator pos, end = m_format_map.map().end(); 405 for (pos = m_format_map.map().begin(); pos != end; pos++) 406 { 407 lldb::RegularExpressionSP regex = pos->first; 408 if (strcmp(regex->GetText(), key.AsCString()) == 0) 409 { 410 value = pos->second; 411 return true; 412 } 413 } 414 return false; 415 } 416 417 bool 418 Get (const FormattersMatchVector& candidates, 419 MapValueType& entry, 420 uint32_t *reason) 421 { 422 for (const FormattersMatchCandidate& candidate : candidates) 423 { 424 if (Get(candidate.GetTypeName(),entry)) 425 { 426 if (candidate.IsMatch(entry) == false) 427 { 428 entry.reset(); 429 continue; 430 } 431 else 432 { 433 if(reason) 434 *reason = candidate.GetReason(); 435 return true; 436 } 437 } 438 } 439 return false; 440 } 441}; 442 443} // namespace lldb_private 444 445#endif // lldb_FormattersContainer_h_ 446