blob: 77c1ad9291d5d888bb682a146a6696f260e31a22 [file] [log] [blame]
// Copyright 2018 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 LIB_COMPONENT_CPP_OBJECT_DIR_H_
#define LIB_COMPONENT_CPP_OBJECT_DIR_H_
#include "expose.h"
namespace component {
// An |ObjectPath| describes a specific path between children objects, which may
// be defined statically within a file to impose type-safety for find()
// operations.
//
// Example:
// const ObjectPath CONTENTS = {"container", "child", "contents"};
// obj->find(CONTENTS);
using ObjectPath = std::initializer_list<const char*>;
// |ObjectDir| is a wrapper class around the raw |Object| class.
// While |Object| deals with the individual properties, metrics, and children
// related to a single |Object|, |ObjectDir| provides a lightweight wrapper
// around the |Object| interface to support higher-level operations, including:
// * Tree traversal
// * Property setters
// * Metric setters
// * Children setters/getters
//
// This class is thread-safe; it simply wraps a single |Object|, which is itself
// thread-safe.
class ObjectDir {
public:
// Constructs an empty |ObjectDir|, satisfying !!(*this) == false.
ObjectDir();
// Constructs an |ObjectDir| wrapping the given |Object|.
explicit ObjectDir(fbl::RefPtr<Object> object);
// Construct a new |ObjectDir| wrapping the given raw object pointer.
static ObjectDir Wrap(Object* object) {
return ObjectDir(fbl::WrapRefPtr(object));
}
// Construct a new |ObjectDir| wrapping a new Object with the given name.
static ObjectDir Make(std::string name) {
return ObjectDir(fbl::AdoptRef(new Object(std::move(name))));
}
// The boolean value of an |ObjectDir| is true if and only if the wrapped
// object reference is not empty.
operator bool() const { return object_.get(); }
// Obtains a reference to the wrapped |Object|.
fbl::RefPtr<Object> object() const { return object_; }
fbl::String name() const { return (*this) ? object_->name() : ""; }
// Finds a child |Object| by path, and wraps it in an |ObjectDir|.
// If |initialize| is true, this method initialized all objects along the path
// that do not exist. Otherwise, it returns an empty |ObjectDir| if any
// |Object| along the path does not exist.
ObjectDir find(ObjectPath path, bool initialize = true) const;
// Sets a property on this object to the given value.
template <typename T>
bool set_prop(std::string name, T value) const {
return inner_set_prop({}, std::move(name), Property(std::move(value)));
}
// Sets a property on the child specified by path to the given value.
// All objects along the path that do not exist will be initialized.
template <typename T>
typename std::enable_if_t<std::is_lvalue_reference<T>::value, bool>::type
set_prop(ObjectPath path, std::string name, T value) const {
return inner_set_prop(std::move(path), std::move(name),
Property(std::move(value)));
}
// Sets a metric on this object to the given value.
bool set_metric(std::string name, Metric metric) const {
return set_metric({}, std::move(name), std::move(metric));
}
// Sets a metric on the child specified by path to use the given value.
// All objects along the path that do not exist will be initialized.
bool set_metric(ObjectPath path, std::string name, Metric metric) const;
// Adds to a metric on this object.
template <typename T>
bool add_metric(std::string name, T amount) const {
return add_metric({}, std::move(name), amount);
}
// Subtracts from a metric on this object.
template <typename T>
bool sub_metric(std::string name, T amount) const {
return sub_metric({}, std::move(name), amount);
}
// Adds to a metric on a child specified by path.
// All objects along the path that do not exist will be initialized.
template <typename T>
bool add_metric(ObjectPath path, std::string name, T amount) const {
return object_ ? find(path).object()->AddMetric(name, amount) : false;
}
// Subtracts from a metric on a child specified by path.
// All objects along the path that do not exist will be initialized.
template <typename T>
bool sub_metric(ObjectPath path, std::string name, T amount) const {
return object_ ? find(path).object()->SubMetric(name, amount) : false;
}
// Sets a child on this object to the given object.
void set_child(fbl::RefPtr<Object> obj) const {
set_child({}, std::move(obj));
}
// Sets a child on the child specified by path to the given object.
// All objects along the path that do not exist will be initialized.
void set_child(ObjectPath path, fbl::RefPtr<Object> obj) const;
// Sets the dynamic child callback on this object.
void set_children_callback(Object::ChildrenCallback callback) const {
set_children_callback({}, std::move(callback));
}
// Sets the dynamic child callback on the child specified by path.
// All objects along the path that do not exist will be initialized.
void set_children_callback(ObjectPath path,
Object::ChildrenCallback callback) const;
private:
// Inner implementation of setting properties by path.
bool inner_set_prop(ObjectPath path, std::string name,
Property property) const;
// The wrapper object.
fbl::RefPtr<Object> object_;
};
} // namespace component
#endif // LIB_COMPONENT_CPP_OBJECT_DIR_H_