Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / app / MessageDef / AttributePath.cpp
1 /**
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2018 Google LLC.
5  *    Copyright (c) 2016-2017 Nest Labs, Inc.
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18 /**
19  *    @file
20  *      This file defines AttributePath parser and builder in CHIP interaction model
21  *
22  */
23
24 #include "AttributePath.h"
25 #include "MessageDefHelper.h"
26
27 #include <inttypes.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 using namespace chip;
32 using namespace chip::TLV;
33
34 namespace chip {
35 namespace app {
36 CHIP_ERROR AttributePath::Parser::Init(const chip::TLV::TLVReader & aReader)
37 {
38     CHIP_ERROR err = CHIP_NO_ERROR;
39
40     // make a copy of the reader here
41     mReader.Init(aReader);
42
43     VerifyOrExit(chip::TLV::kTLVType_List == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
44
45     // This is just a dummy, as we're not going to exit this container ever
46     chip::TLV::TLVType dummyContainerType;
47     // enter into the Path
48     err = mReader.EnterContainer(dummyContainerType);
49     SuccessOrExit(err);
50
51 exit:
52     ChipLogFunctError(err);
53
54     return err;
55 }
56
57 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
58 CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const
59 {
60     CHIP_ERROR err           = CHIP_NO_ERROR;
61     uint16_t TagPresenceMask = 0;
62     chip::TLV::TLVReader reader;
63
64     PRETTY_PRINT("AttributePath =");
65     PRETTY_PRINT("{");
66
67     // make a copy of the Path reader
68     reader.Init(mReader);
69
70     while (CHIP_NO_ERROR == (err = reader.Next()))
71     {
72         VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
73         switch (chip::TLV::TagNumFromTag(reader.GetTag()))
74         {
75         case kCsTag_NodeId:
76             // check if this tag has appeared before
77             VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NodeId)), err = CHIP_ERROR_INVALID_TLV_TAG);
78             TagPresenceMask |= (1 << kCsTag_NodeId);
79             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
80
81 #if CHIP_DETAIL_LOGGING
82             {
83                 uint64_t nodeId;
84                 reader.Get(nodeId);
85                 PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId);
86             }
87 #endif // CHIP_DETAIL_LOGGING
88             break;
89         case kCsTag_EndpointId:
90             // check if this tag has appeared before
91             VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG);
92             TagPresenceMask |= (1 << kCsTag_EndpointId);
93             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
94 #if CHIP_DETAIL_LOGGING
95             {
96                 uint16_t endpointId;
97                 reader.Get(endpointId);
98                 PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
99             }
100 #endif // CHIP_DETAIL_LOGGING
101             break;
102         case kCsTag_ClusterId:
103             // check if this tag has appeared before
104             VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG);
105             TagPresenceMask |= (1 << kCsTag_ClusterId);
106             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
107
108 #if CHIP_DETAIL_LOGGING
109             if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
110             {
111                 chip::ClusterId clusterId;
112                 reader.Get(clusterId);
113                 PRETTY_PRINT("\tClusterId = 0x%" PRIx32 ",", clusterId);
114             }
115 #endif // CHIP_DETAIL_LOGGING
116             break;
117         case kCsTag_FieldId:
118             // check if this tag has appeared before
119             VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_FieldId)), err = CHIP_ERROR_INVALID_TLV_TAG);
120             TagPresenceMask |= (1 << kCsTag_FieldId);
121             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
122 #if CHIP_DETAIL_LOGGING
123             {
124                 uint8_t fieldTag;
125                 reader.Get(fieldTag);
126                 PRETTY_PRINT("\tFieldTag = 0x%" PRIx8 ",", fieldTag);
127             }
128 #endif // CHIP_DETAIL_LOGGING
129             break;
130         case kCsTag_ListIndex:
131             // check if this tag has appeared before
132             VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ListIndex)), err = CHIP_ERROR_INVALID_TLV_TAG);
133             TagPresenceMask |= (1 << kCsTag_ListIndex);
134             VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
135 #if CHIP_DETAIL_LOGGING
136             if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
137             {
138                 uint16_t listIndex;
139                 reader.Get(listIndex);
140                 PRETTY_PRINT("\tListIndex = 0x%" PRIx16 ",", listIndex);
141             }
142 #endif // CHIP_DETAIL_LOGGING
143             break;
144         default:
145             ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
146         }
147     }
148
149     PRETTY_PRINT("}");
150     PRETTY_PRINT("\t");
151     // if we have exhausted this container
152     if (CHIP_END_OF_TLV == err)
153     {
154         // check for required fields:
155         const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_ClusterId);
156
157         if ((TagPresenceMask & RequiredFields) == RequiredFields)
158         {
159             err = CHIP_NO_ERROR;
160         }
161         else
162         {
163             err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH;
164         }
165     }
166     SuccessOrExit(err);
167
168 exit:
169     ChipLogFunctError(err);
170
171     return err;
172 }
173 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
174
175 CHIP_ERROR AttributePath::Parser::GetNodeId(chip::NodeId * const apNodeId) const
176 {
177     return GetUnsignedInteger(kCsTag_NodeId, apNodeId);
178 }
179
180 CHIP_ERROR AttributePath::Parser::GetEndpointId(chip::EndpointId * const apEndpointId) const
181 {
182     return GetUnsignedInteger(kCsTag_EndpointId, apEndpointId);
183 }
184
185 CHIP_ERROR AttributePath::Parser::GetClusterId(chip::ClusterId * const apClusterId) const
186 {
187     return GetUnsignedInteger(kCsTag_ClusterId, apClusterId);
188 }
189
190 CHIP_ERROR AttributePath::Parser::GetFieldId(uint8_t * const apFieldId) const
191 {
192     return GetUnsignedInteger(kCsTag_FieldId, apFieldId);
193 }
194
195 CHIP_ERROR AttributePath::Parser::GetListIndex(uint16_t * const apListIndex) const
196 {
197     return GetUnsignedInteger(kCsTag_ListIndex, apListIndex);
198 }
199
200 CHIP_ERROR AttributePath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const uint64_t aTag)
201 {
202     mpWriter = apWriter;
203     mError   = mpWriter->StartContainer(aTag, chip::TLV::kTLVType_List, mOuterContainerType);
204     SuccessOrExit(mError);
205
206 exit:
207     ChipLogFunctError(mError);
208     return mError;
209 }
210
211 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter)
212 {
213     return _Init(apWriter, chip::TLV::AnonymousTag);
214 }
215
216 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
217 {
218     return _Init(apWriter, chip::TLV::ContextTag(aContextTagToUse));
219 }
220
221 AttributePath::Builder & AttributePath::Builder::NodeId(const uint64_t aNodeId)
222 {
223     // skip if error has already been set
224     SuccessOrExit(mError);
225
226     mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NodeId), aNodeId);
227     ChipLogFunctError(mError);
228
229 exit:
230
231     return *this;
232 }
233
234 AttributePath::Builder & AttributePath::Builder::EndpointId(const chip::EndpointId aEndpointId)
235 {
236     // skip if error has already been set
237     SuccessOrExit(mError);
238
239     mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId);
240     ChipLogFunctError(mError);
241
242 exit:
243     return *this;
244 }
245
246 AttributePath::Builder & AttributePath::Builder::ClusterId(const chip::ClusterId aClusterId)
247 {
248     // skip if error has already been set
249     SuccessOrExit(mError);
250
251     mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ClusterId), aClusterId);
252     ChipLogFunctError(mError);
253
254 exit:
255     return *this;
256 }
257
258 AttributePath::Builder & AttributePath::Builder::FieldId(const uint8_t aFieldId)
259 {
260     // skip if error has already been set
261     SuccessOrExit(mError);
262
263     mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_FieldId), aFieldId);
264     ChipLogFunctError(mError);
265
266 exit:
267     return *this;
268 }
269
270 AttributePath::Builder & AttributePath::Builder::ListIndex(const uint16_t aListIndex)
271 {
272     // skip if error has already been set
273     SuccessOrExit(mError);
274
275     mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ListIndex), aListIndex);
276     ChipLogFunctError(mError);
277
278 exit:
279     return *this;
280 }
281
282 AttributePath::Builder & AttributePath::Builder::EndOfAttributePath()
283 {
284     EndOfContainer();
285     return *this;
286 }
287 }; // namespace app
288 }; // namespace chip