| // 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. |
| |
| #include "lib/inspect/inspect.h" |
| |
| #include "lib/inspect-vmo/block.h" |
| |
| using component::ObjectDir; |
| |
| namespace inspect { |
| |
| template <> |
| component::Metric internal::MakeMetric<int64_t>(int64_t value) { |
| return component::IntMetric(value); |
| } |
| |
| template <> |
| component::Metric internal::MakeMetric<uint64_t>(uint64_t value) { |
| return component::UIntMetric(value); |
| } |
| |
| template <> |
| component::Metric internal::MakeMetric<double>(double value) { |
| return component::DoubleMetric(value); |
| } |
| |
| template <> |
| void internal::RemoveEntity<component::Property>(component::Object* object, |
| const std::string& name) { |
| object->RemoveProperty(name); |
| } |
| |
| template <> |
| void internal::RemoveEntity<component::Metric>(component::Object* object, |
| const std::string& name) { |
| object->RemoveMetric(name); |
| } |
| |
| LazyMetric::LazyMetric() {} |
| |
| LazyMetric::LazyMetric(internal::EntityWrapper<component::Metric> entity) |
| : entity_(std::move(entity)) {} |
| void LazyMetric::Set(MetricCallback callback) { |
| if (entity_) { |
| entity_->ParentObject()->SetMetric( |
| entity_->name(), component::CallbackMetric(std::move(callback))); |
| } |
| } |
| |
| #define DEFINE_PROPERTY_METHODS(CLASS, TYPE) \ |
| CLASS::CLASS() {} \ |
| CLASS::CLASS(internal::EntityWrapper<component::Property> entity) { \ |
| entity_.template emplace<kEntityWrapperVariant>(std::move(entity)); \ |
| } \ |
| CLASS::CLASS(vmo::Property entity) { \ |
| entity_.template emplace<kVmoVariant>(std::move(entity)); \ |
| } \ |
| void CLASS::Set(TYPE value) { \ |
| if (entity_.index() == kEntityWrapperVariant) { \ |
| auto& entity = entity_.template get<kEntityWrapperVariant>(); \ |
| entity.ParentObject()->SetProperty( \ |
| entity.name(), component::Property(std::move(value))); \ |
| } else if (entity_.index() == kVmoVariant) { \ |
| entity_.template get<kVmoVariant>().Set( \ |
| {(const char*)value.data(), value.size()}); \ |
| } \ |
| } |
| |
| #define DEFINE_LAZY_PROPERTY_METHODS(CLASS, TYPE) \ |
| CLASS::CLASS() {} \ |
| CLASS::CLASS(internal::EntityWrapper<component::Property> entity) \ |
| : entity_(std::move(entity)) {} \ |
| void CLASS::Set(TYPE value) { \ |
| if (entity_) { \ |
| entity_->ParentObject()->SetProperty( \ |
| entity_->name(), component::Property(std::move(value))); \ |
| } \ |
| } |
| |
| DEFINE_PROPERTY_METHODS(StringProperty, std::string) |
| DEFINE_PROPERTY_METHODS(ByteVectorProperty, VectorValue) |
| DEFINE_LAZY_PROPERTY_METHODS(LazyStringProperty, StringValueCallback) |
| DEFINE_LAZY_PROPERTY_METHODS(LazyByteVectorProperty, VectorValueCallback) |
| |
| ChildrenCallback::ChildrenCallback() {} |
| |
| ChildrenCallback::ChildrenCallback(std::shared_ptr<component::Object> object) |
| : parent_obj_(std::move(object)) {} |
| |
| ChildrenCallback::~ChildrenCallback() { |
| // Remove the entity from its parent if it has a parent. |
| if (parent_obj_) { |
| parent_obj_->ClearChildrenCallback(); |
| } |
| } |
| |
| void ChildrenCallback::Set(ChildrenCallbackFunction callback) { |
| if (parent_obj_) { |
| parent_obj_->SetChildrenCallback(std::move(callback)); |
| } |
| } |
| |
| ChildrenCallback& ChildrenCallback::operator=(ChildrenCallback&& other) { |
| // Remove the entity from its parent before moving values over. |
| if (parent_obj_ && parent_obj_.get() != other.parent_obj_.get()) { |
| parent_obj_->ClearChildrenCallback(); |
| } |
| parent_obj_ = std::move(other.parent_obj_); |
| return *this; |
| } |
| |
| Object::Object(std::string name) |
| : Object(component::ExposedObject(std::move(name))) {} |
| |
| Object::Object(ObjectDir object_dir) |
| : Object(component::ExposedObject(std::move(object_dir))) {} |
| |
| Object::Object(vmo::Object object) { |
| object_.template emplace<kVmoVariant>(std::move(object)); |
| } |
| |
| Object::Object(component::ExposedObject object) { |
| object_.template emplace<kComponentVariant>(std::move(object)); |
| } |
| |
| fuchsia::inspect::Object Object::object() const { |
| if (object_.index() == kComponentVariant) { |
| return object_.template get<kComponentVariant>().object()->ToFidl(); |
| } |
| return fuchsia::inspect::Object(); |
| } |
| |
| component::ObjectDir Object::object_dir() const { |
| if (object_.index() == kComponentVariant) { |
| return component::ObjectDir( |
| object_.template get<kComponentVariant>().object()); |
| } |
| return component::ObjectDir(); |
| } |
| |
| component::Object::StringOutputVector Object::children() const { |
| if (object_.index() == kComponentVariant) { |
| return object_.template get<kComponentVariant>().object()->GetChildren(); |
| } |
| return component::Object::StringOutputVector(); |
| } |
| |
| Object Object::CreateChild(std::string name) { |
| if (object_.index() == kComponentVariant) { |
| component::ExposedObject child(std::move(name)); |
| object_.template get<kComponentVariant>().add_child(&child); |
| return Object(std::move(child)); |
| } else if (object_.index() == kVmoVariant) { |
| return Object( |
| object_.template get<kVmoVariant>().CreateChild(std::move(name))); |
| } |
| return Object(); |
| } |
| |
| IntMetric Object::CreateIntMetric(std::string name, int64_t value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetMetric(name, component::IntMetric(value)); |
| return IntMetric( |
| internal::EntityWrapper<component::Metric>(std::move(name), object)); |
| } else if (object_.index() == kVmoVariant) { |
| return IntMetric(object_.template get<kVmoVariant>().CreateIntMetric( |
| std::move(name), value)); |
| } |
| |
| return IntMetric(); |
| } |
| |
| UIntMetric Object::CreateUIntMetric(std::string name, uint64_t value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetMetric(name, component::UIntMetric(value)); |
| return UIntMetric( |
| internal::EntityWrapper<component::Metric>(std::move(name), object)); |
| } else if (object_.index() == kVmoVariant) { |
| return UIntMetric(object_.template get<kVmoVariant>().CreateUintMetric( |
| std::move(name), value)); |
| } |
| |
| return UIntMetric(); |
| } |
| |
| DoubleMetric Object::CreateDoubleMetric(std::string name, double value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetMetric(name, component::DoubleMetric(value)); |
| return DoubleMetric( |
| internal::EntityWrapper<component::Metric>(std::move(name), object)); |
| } else if (object_.index() == kVmoVariant) { |
| return DoubleMetric(object_.template get<kVmoVariant>().CreateDoubleMetric( |
| std::move(name), value)); |
| } |
| |
| return DoubleMetric(); |
| } |
| |
| IntArray Object::CreateIntArray(std::string name, size_t slots) { |
| return CreateIntArray(std::move(name), slots, vmo::ArrayFormat::kDefault); |
| } |
| |
| IntArray Object::CreateIntArray(std::string name, size_t slots, |
| vmo::ArrayFormat format) { |
| if (object_.index() == kVmoVariant) { |
| return IntArray(object_.template get<kVmoVariant>().CreateIntArray( |
| name, slots, format)); |
| } |
| return IntArray(); |
| } |
| |
| UIntArray Object::CreateUIntArray(std::string name, size_t slots) { |
| return CreateUIntArray(std::move(name), slots, vmo::ArrayFormat::kDefault); |
| } |
| |
| UIntArray Object::CreateUIntArray(std::string name, size_t slots, |
| vmo::ArrayFormat format) { |
| if (object_.index() == kVmoVariant) { |
| return UIntArray(object_.template get<kVmoVariant>().CreateUintArray( |
| name, slots, format)); |
| } |
| return UIntArray(); |
| } |
| |
| DoubleArray Object::CreateDoubleArray(std::string name, size_t slots) { |
| return CreateDoubleArray(std::move(name), slots, vmo::ArrayFormat::kDefault); |
| } |
| |
| DoubleArray Object::CreateDoubleArray(std::string name, size_t slots, |
| vmo::ArrayFormat format) { |
| if (object_.index() == kVmoVariant) { |
| return DoubleArray(object_.template get<kVmoVariant>().CreateDoubleArray( |
| name, slots, format)); |
| } |
| return DoubleArray(); |
| } |
| |
| LinearIntHistogramMetric Object::CreateLinearIntHistogramMetric( |
| std::string name, int64_t floor, int64_t step_size, size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return LinearIntHistogramMetric( |
| object_.template get<kVmoVariant>().CreateLinearIntHistogram( |
| name, floor, step_size, buckets)); |
| } |
| return LinearIntHistogramMetric(); |
| } |
| |
| LinearUIntHistogramMetric Object::CreateLinearUIntHistogramMetric( |
| std::string name, uint64_t floor, uint64_t step_size, size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return LinearUIntHistogramMetric( |
| object_.template get<kVmoVariant>().CreateLinearUintHistogram( |
| name, floor, step_size, buckets)); |
| } |
| return LinearUIntHistogramMetric(); |
| } |
| |
| LinearDoubleHistogramMetric Object::CreateLinearDoubleHistogramMetric( |
| std::string name, double floor, double step_size, size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return LinearDoubleHistogramMetric( |
| object_.template get<kVmoVariant>().CreateLinearDoubleHistogram( |
| name, floor, step_size, buckets)); |
| } |
| return LinearDoubleHistogramMetric(); |
| } |
| |
| ExponentialIntHistogramMetric Object::CreateExponentialIntHistogramMetric( |
| std::string name, int64_t floor, int64_t initial_step, |
| int64_t step_multiplier, size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return ExponentialIntHistogramMetric( |
| object_.template get<kVmoVariant>().CreateExponentialIntHistogram( |
| name, floor, initial_step, step_multiplier, buckets)); |
| } |
| return ExponentialIntHistogramMetric(); |
| } |
| |
| ExponentialUIntHistogramMetric Object::CreateExponentialUIntHistogramMetric( |
| std::string name, uint64_t floor, uint64_t initial_step, |
| uint64_t step_multiplier, size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return ExponentialUIntHistogramMetric( |
| object_.template get<kVmoVariant>().CreateExponentialUintHistogram( |
| name, floor, initial_step, step_multiplier, buckets)); |
| } |
| return ExponentialUIntHistogramMetric(); |
| } |
| |
| ExponentialDoubleHistogramMetric Object::CreateExponentialDoubleHistogramMetric( |
| std::string name, double floor, double initial_step, double step_multiplier, |
| size_t buckets) { |
| if (object_.index() == kVmoVariant) { |
| return ExponentialDoubleHistogramMetric( |
| object_.template get<kVmoVariant>().CreateExponentialDoubleHistogram( |
| name, floor, initial_step, step_multiplier, buckets)); |
| } |
| return ExponentialDoubleHistogramMetric(); |
| } |
| |
| LazyMetric Object::CreateLazyMetric(std::string name, |
| component::Metric::ValueCallback callback) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetMetric(name, component::CallbackMetric(std::move(callback))); |
| return LazyMetric( |
| internal::EntityWrapper<component::Metric>(std::move(name), object)); |
| } |
| return LazyMetric(); |
| } |
| |
| StringProperty Object::CreateStringProperty(std::string name, |
| std::string value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetProperty(name, component::Property(std::move(value))); |
| return StringProperty( |
| internal::EntityWrapper<component::Property>(std::move(name), object)); |
| } else if (object_.index() == kVmoVariant) { |
| return StringProperty(object_.template get<kVmoVariant>().CreateProperty( |
| std::move(name), {value.data(), value.size()}, |
| inspect::vmo::PropertyFormat::kUtf8)); |
| } |
| |
| return StringProperty(); |
| } |
| |
| ByteVectorProperty Object::CreateByteVectorProperty(std::string name, |
| VectorValue value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetProperty(name, component::Property(std::move(value))); |
| return ByteVectorProperty( |
| internal::EntityWrapper<component::Property>(std::move(name), object)); |
| } else if (object_.index() == kVmoVariant) { |
| return ByteVectorProperty( |
| object_.template get<kVmoVariant>().CreateProperty( |
| std::move(name), {(const char*)value.data(), value.size()}, |
| inspect::vmo::PropertyFormat::kBinary)); |
| } |
| |
| return ByteVectorProperty(); |
| } |
| |
| LazyStringProperty Object::CreateLazyStringProperty(std::string name, |
| StringValueCallback value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetProperty(name, component::Property(std::move(value))); |
| return LazyStringProperty( |
| internal::EntityWrapper<component::Property>(std::move(name), object)); |
| } |
| return LazyStringProperty(); |
| } |
| |
| LazyByteVectorProperty Object::CreateLazyByteVectorProperty( |
| std::string name, VectorValueCallback value) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetProperty(name, component::Property(std::move(value))); |
| return LazyByteVectorProperty( |
| internal::EntityWrapper<component::Property>(std::move(name), object)); |
| } |
| return LazyByteVectorProperty(); |
| } |
| |
| ChildrenCallback Object::CreateChildrenCallback( |
| ChildrenCallbackFunction callback) { |
| if (object_.index() == kComponentVariant) { |
| auto object = object_.template get<kComponentVariant>().object(); |
| object->SetChildrenCallback(std::move(callback)); |
| return ChildrenCallback(object); |
| } |
| return ChildrenCallback(); |
| } |
| |
| namespace internal { |
| struct TreeState { |
| // The root of the tree. |
| Object root; |
| |
| // The VMO inspector object for this tree. |
| vmo::Inspector inspector; |
| }; |
| }; // namespace internal |
| |
| const TreeSettings kDefaultTreeSettings = {.initial_size = 4096, |
| .maximum_size = 256 * 1024}; |
| |
| Tree::Tree(std::unique_ptr<internal::TreeState> state) |
| : state_(std::move(state)) {} |
| |
| Tree::~Tree() {} |
| |
| const zx::vmo& Tree::GetVmo() const { return state_->inspector.GetVmo(); } |
| |
| Object& Tree::GetRoot() const { return state_->root; } |
| |
| Tree Inspector::CreateTree(std::string name) { |
| return CreateTree(std::move(name), kDefaultTreeSettings); |
| } |
| |
| Tree Inspector::CreateTree(std::string name, TreeSettings settings) { |
| auto state = std::make_unique<internal::TreeState>(); |
| state->inspector = |
| vmo::Inspector(settings.initial_size, settings.maximum_size); |
| state->root = Object(state->inspector.CreateObject(name.c_str())); |
| |
| return Tree(std::move(state)); |
| } |
| |
| std::string UniqueName(const std::string& prefix) { |
| return component::ExposedObject::UniqueName(prefix); |
| } |
| |
| } // namespace inspect |