1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef REFERENCE_H_
18 
19 #define REFERENCE_H_
20 
21 #include <android-base/logging.h>
22 #include <hidl-util/FQName.h>
23 
24 #include "DocComment.h"
25 #include "Location.h"
26 
27 namespace android {
28 
29 /**
30  * Reference placeholder
31  */
32 template <class T>
33 struct Reference {
34     Reference() = default;
~ReferenceReference35     virtual ~Reference() {}
36 
ReferenceReference37     Reference(const FQName& fqName, const Location& location)
38         : mResolved(nullptr), mFqName(fqName), mLocation(location) {}
39 
ReferenceReference40     Reference(T* type, const Location& location) : mResolved(type), mLocation(location) {
41         CHECK(type != nullptr);
42     }
43 
44     template <class OtherT>
ReferenceReference45     Reference(const Reference<OtherT>& ref)
46         : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(ref.mLocation) {}
47 
48     template <class OtherT>
ReferenceReference49     Reference(const Reference<OtherT>& ref, const Location& location)
50         : mResolved(ref.mResolved), mFqName(ref.mFqName), mLocation(location) {}
51 
52     /* Returns true iff referred type is resolved
53        Referred type's field might be not resolved */
isResolvedReference54     bool isResolved() const { return mResolved != nullptr; }
55 
56     T* operator->() { return get(); }
57     const T* operator->() const { return get(); }
58 
59     /* Returns referenced object.
60        If a type is referenced, all typedefs are unwrapped. */
getReference61     T* get() {
62         CHECK(mResolved != nullptr);
63         return mResolved->resolve();
64     }
getReference65     const T* get() const {
66         CHECK(mResolved != nullptr);
67         return mResolved->resolve();
68     }
69 
70     /* Returns exact referenced object.
71        If a type is referenced, typedefs are not unwraped. */
shallowGetReference72     T* shallowGet() {
73         CHECK(mResolved != nullptr);
74         return mResolved;
75     }
shallowGetReference76     const T* shallowGet() const {
77         CHECK(mResolved != nullptr);
78         return mResolved;
79     }
80 
setReference81     void set(T* resolved) {
82         CHECK(!isResolved());
83         CHECK(resolved != nullptr);
84         mResolved = resolved;
85     }
86 
87     /* Returns true iff this is reference to null:
88        not resolved and has not name for lookup */
isEmptyReferenceReference89     bool isEmptyReference() const { return !isResolved() && !hasLookupFqName(); }
90 
getLookupFqNameReference91     const FQName& getLookupFqName() const {
92         CHECK(hasLookupFqName());
93         return mFqName;
94     }
95 
hasLocationReference96     bool hasLocation() const { return mLocation.isValid(); }
97 
locationReference98     const Location& location() const {
99         CHECK(hasLocation());
100         return mLocation;
101     }
102 
103    private:
104     /* Referred type */
105     T* mResolved = nullptr;
106     /* Reference name for lookup */
107     FQName mFqName;
108     /* Reference location is mainly used for printing errors
109        and handling forward reference restrictions */
110     Location mLocation;
111 
hasLookupFqNameReference112     bool hasLookupFqName() const {
113         // Valid only while not resolved to prevent confusion when
114         // ref.hasLookupFqName() is false while ref,get()->fqName is valid.
115         CHECK(!isResolved());
116         return mFqName.isValid();
117     }
118 
119     template <class OtherT>
120     friend struct Reference;
121 };
122 
123 template <class T>
124 struct NamedReference : public Reference<T>, DocCommentable {
NamedReferenceNamedReference125     NamedReference(const std::string& name, const Reference<T>& reference, const Location& location)
126         : Reference<T>(reference, location), mName(name) {}
127 
nameNamedReference128     const std::string& name() const { return mName; }
129 
130     // TODO(b/64715470) Legacy
typeNamedReference131     const T& type() const { return *Reference<T>::get(); }
132 
133    private:
134     const std::string mName;
135 };
136 
137 }  // namespace android
138 
139 #endif  // REFERENCE_H_
140