blob: 9bee336efca22c9e8e0ae1c33a47fc706f6aef20 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_PRETTY_TREE_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_PRETTY_TREE_H_
#include "src/developer/debug/zxdb/expr/eval_callback.h"
#include "src/developer/debug/zxdb/expr/pretty_type.h"
namespace zxdb {
// Pretty printers for C++ STL "trees" (sets and maps).
//
//
// SET ITERATORS
// -------------
// In our STL a tree iterator for std::set<int> looks like this:
//
// std::__2::__tree_const_iterator<int, std::__2::__tree_node<int, void *> *, long> {
// __iter_pointer __ptr_;
// }
//
// That pointer has a "left" member but no values. It's nonspecific to the tree type. To get the
// value you have to cast that pointer to a "__node_pointer" which looks like this:
//
// std::__2::__tree_node<int, void *> {
// std::__2::__tree_node_base<void *> { // BASE CLASS
// std::__2::__tree_node_base<void *>::pointer __right_;
// std::__2::__tree_node_base<void *>::__parent_pointer __parent_;
// bool __is_black_;
// }
// std::__2::__tree_node<int, void *>::__node_value_type __value_; // ACTUAL DATA
// }
//
//
// MAP ITERATORS
// -------------
// A std::map::iterator is the same except the above structure is enclosed in another layer of
// indirection. The tree "value" is a "std::__2::__value_type<Key, Value>".
//
// std::__2::__map_iterator<std::__2::__tree_iterator<std::__2::__value_type<Key, Value>, ... {
// <std::__2::__tree_iterator<std::__2::__value_type<Key, Value>, ...> __i_;
// }
//
//
// IMPLEMENTATION
// --------------
// This could be replaced with a PrettyPointer type if we have the ability to express "the type
// name of the type being pretty-printed" and "the name of a template parameter". Then the "pointer"
// of this class would then be
//
// (MY_TYPE::__node_pointer)__ptr_ // for set
// (TEMPLATE_PARAM_0::__node_pointer)__i_.__ptr_ // for map
//
// For now, this provides a dynamic expression to the PrettyPointer base class that we compute from
// the type name.
// std::set<*>::iterator
// A "tree" is the backing store for a set, which in turn "map" wraps.
class PrettyTreeIterator : public PrettyType {
public:
PrettyTreeIterator() : PrettyType() {}
void Format(FormatNode* node, const FormatOptions& options,
const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) override;
EvalFunction GetDereferencer() const override;
// Computes the pointed-to value for the given iterator and calls the callback with it.
static void GetIteratorValue(const fxl::RefPtr<EvalContext>& context, const ExprValue& iter,
EvalCallback cb);
};
// std::map<*>::iterator
class PrettyMapIterator : public PrettyType {
public:
PrettyMapIterator() : PrettyType() {}
void Format(FormatNode* node, const FormatOptions& options,
const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) override;
EvalFunction GetDereferencer() const override;
// Computes the pointed-to value for the given iterator and calls the callback with it.
static void GetIteratorValue(const fxl::RefPtr<EvalContext>& context, const ExprValue& iter,
EvalCallback cb);
};
// std::set and std::map.
class PrettyTree : public PrettyType {
public:
// The container name should be "std::set" or "std::map".
PrettyTree(const std::string& container_name);
void Format(FormatNode* node, const FormatOptions& options,
const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) override;
private:
std::string container_name_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_PRETTY_TREE_H_