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 <string>
25 
26 #include "DocComment.h"
27 #include "Location.h"
28 
29 namespace android {
30 
31 /**
32  * Reference placeholder
33  */
34 template <class T>
35 struct Reference {
36     Reference() = default;
~ReferenceReference37     virtual ~Reference() {}
38 
39     Reference(const std::string& localName, const FQName& fqName, const Location& location,
40               bool definedInline = false)
mResolvedReference41         : mResolved(nullptr),
42           mFqName(fqName),
43           mLocation(location),
44           mDefinedInline(definedInline),
45           mLocalName(localName) {}
46 
47     Reference(const std::string& localName, T* type, const Location& location,
48               bool definedInline = false)
mResolvedReference49         : mResolved(type),
50           mLocation(location),
51           mDefinedInline(definedInline),
52           mLocalName(localName) {
53         CHECK(type != nullptr);
54     }
55 
56     template <class OtherT>
ReferenceReference57     Reference(const Reference<OtherT>& ref)
58         : mResolved(ref.mResolved),
59           mFqName(ref.mFqName),
60           mLocation(ref.mLocation),
61           mDefinedInline(ref.mDefinedInline),
62           mLocalName(ref.mLocalName) {}
63 
64     template <class OtherT>
ReferenceReference65     Reference(const Reference<OtherT>& ref, const Location& location)
66         : mResolved(ref.mResolved),
67           mFqName(ref.mFqName),
68           mLocation(location),
69           mDefinedInline(ref.mDefinedInline),
70           mLocalName(ref.mLocalName) {}
71 
72     /* Returns true iff referred type is resolved
73        Referred type's field might be not resolved */
isResolvedReference74     bool isResolved() const { return mResolved != nullptr; }
75 
76     T* operator->() { return get(); }
77     const T* operator->() const { return get(); }
78 
79     /* Returns referenced object.
80        If a type is referenced, all typedefs are unwrapped. */
getReference81     T* get() {
82         CHECK(mResolved != nullptr);
83         return mResolved->resolve();
84     }
getReference85     const T* get() const {
86         CHECK(mResolved != nullptr);
87         return mResolved->resolve();
88     }
89 
90     /* Returns exact referenced object.
91        If a type is referenced, typedefs are not unwraped. */
shallowGetReference92     T* shallowGet() {
93         CHECK(mResolved != nullptr);
94         return mResolved;
95     }
shallowGetReference96     const T* shallowGet() const {
97         CHECK(mResolved != nullptr);
98         return mResolved;
99     }
100 
setReference101     void set(T* resolved) {
102         CHECK(!isResolved());
103         CHECK(resolved != nullptr);
104         mResolved = resolved;
105     }
106 
107     /* Returns true iff this is reference to null:
108        not resolved and has not name for lookup */
isEmptyReferenceReference109     bool isEmptyReference() const { return !isResolved() && !hasLookupFqName(); }
110 
getLookupFqNameReference111     const FQName& getLookupFqName() const {
112         CHECK(hasLookupFqName());
113         return mFqName;
114     }
115 
hasLocationReference116     bool hasLocation() const { return mLocation.isValid(); }
117 
locationReference118     const Location& location() const {
119         CHECK(hasLocation());
120         return mLocation;
121     }
122 
definedInlineReference123     bool definedInline() const { return mDefinedInline; }
124 
localNameReference125     const std::string& localName() const { return mLocalName; }
126 
127   private:
128     /* Referred type */
129     T* mResolved = nullptr;
130     /* Reference name for lookup */
131     FQName mFqName;
132     /* Reference location is mainly used for printing errors
133        and handling forward reference restrictions */
134     Location mLocation;
135     /* definedInline is true if T is defined where it is referenced */
136     bool mDefinedInline;
137 
138     /* Name used in the .hal file */
139     std::string mLocalName;
140 
hasLookupFqNameReference141     bool hasLookupFqName() const {
142         // Valid only while not resolved to prevent confusion when
143         // ref.hasLookupFqName() is false while ref,get()->fqName is valid.
144         CHECK(!isResolved());
145         return mFqName != FQName();
146     }
147 
148     template <class OtherT>
149     friend struct Reference;
150 };
151 
152 template <class T>
153 struct NamedReference : public Reference<T>, DocCommentable {
NamedReferenceNamedReference154     NamedReference(const std::string& name, const Reference<T>& reference, const Location& location)
155         : Reference<T>(reference, location), mName(name) {}
156 
nameNamedReference157     const std::string& name() const { return mName; }
158 
159     // TODO(b/64715470) Legacy
typeNamedReference160     const T& type() const { return *Reference<T>::get(); }
161 
162   private:
163     const std::string mName;
164 };
165 
166 }  // namespace android
167 
168 #endif  // REFERENCE_H_
169