forked from cel-expr/cel-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparent_ref.h
More file actions
140 lines (114 loc) · 3.89 KB
/
Copy pathparent_ref.h
File metadata and controls
140 lines (114 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Helper classes for creating 'view' values using parent references.
//
// Can class that inherits from 'SharedValue' can be used as the parent of
// of another value. Note that `SharedValue` should typically not be inherited
// from directly, instead inherit from `List`, `Map`, or `Object`.
//
// Shared values support:
// - Down-casting to a specific implementation through `Shared::cast_if`.
// - Creating self-references that can be used to create 'views' of the data
// owned by the shared value. For example, a 'list of strings' can
// create element `Value` instances that reference (vs copy) the underlying
// string.
#ifndef THIRD_PARTY_CEL_CPP_COMMON_PARENT_REF_H_
#define THIRD_PARTY_CEL_CPP_COMMON_PARENT_REF_H_
#include "absl/types/optional.h"
#include "internal/ref_countable.h"
namespace google {
namespace api {
namespace expr {
namespace common {
class SharedValue;
/**
* An opaque reference to a value that prevents the value from being deleted.
*
* Used to support 'views' by allowing the view prevent a parent value from
* being deleted.
*
* Only constructable via `RefProvider::GetRef`.
*/
class ValueRef {
public:
// Value semantics.
ValueRef() = default;
ValueRef(const ValueRef& other) = default;
ValueRef(ValueRef&& other) = default;
ValueRef& operator=(const ValueRef& other) = default;
ValueRef& operator=(ValueRef&& other) = default;
operator bool() const { return ptr_ != nullptr; }
private:
friend class RefProvider;
internal::ReffedPtr<const SharedValue> ptr_;
explicit ValueRef(const SharedValue* ptr) : ptr_(ptr) {}
};
/**
* A class that can create references for a shared value.
*
* Only constructable via `SharedValue::SelfRefProvider()`
*/
class RefProvider {
public:
RefProvider() = default;
RefProvider(const RefProvider&) = default;
RefProvider(RefProvider&&) = default;
RefProvider& operator=(const RefProvider&) = default;
RefProvider& operator=(RefProvider&&) = default;
/**
* Returns true if a reference is required for the given parent.
*
* False when the parent does not own its value, thus ownership need not be
* tracked.
*/
bool RequiresReference() const { return ptr_ != nullptr; }
ValueRef GetRef() const { return ValueRef(ptr_); }
private:
friend class SharedValue;
friend constexpr RefProvider NoParent();
constexpr explicit RefProvider(const SharedValue* ptr) : ptr_(ptr) {}
const SharedValue* ptr_;
};
constexpr inline RefProvider NoParent() { return RefProvider(nullptr); }
// The type by which a parent reference provider should be passed around as.
//
// A value of absl::nullopt indicates that the parent cannot be referenced.
using ParentRef = absl::optional<RefProvider>;
/** The base class for custom value implementations. */
class SharedValue : public internal::RefCountable {
public:
virtual ~SharedValue() {}
virtual bool owns_value() const = 0;
/**
* Returns a canonical cel expression for the value.
*
* Computation may be expensive.
*/
virtual std::string ToString() const = 0;
/**
* Attempts to cast the given Container to the given type.
*
* Returns nullptr if value is null or is not the requested type.
*/
template <typename T>
static const T* cast_if(const SharedValue* value) {
return dynamic_cast<const T*>(value);
}
protected:
SharedValue() = default;
/**
* Construct a self reference provider, to be passed to a 'view' Value.
*
* `this` must live longer than the returned value.
*
* Returns absl::nullopt if the container cannot be reffed, in which case
* all needed data must be copied.
*
* No synchronization is performed until ParentRef->GetRef() is called, so
* calls to this function do not incur a synchronization performance penalty.
*/
ParentRef SelfRefProvider() const;
};
} // namespace common
} // namespace expr
} // namespace api
} // namespace google
#endif // THIRD_PARTY_CEL_CPP_COMMON_PARENT_REF_H_