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#include "HidDefs.h"
17#include "HidLog.h"
18#include "HidTree.h"
19#include <memory>
20
21namespace HidUtil {
22
23// HidTreeNode
24HidTreeNode::HidTreeNode() : mNodeType(TYPE_UNINITIALIZED), mData(0), mFullUsage(0) {
25}
26
27HidTreeNode::HidTreeNode(std::shared_ptr<HidTreeNode> parent,
28                         uint32_t data, uint32_t fullUsage, int nodeType)
29        : mNodeType(nodeType), mData(data),
30        mFullUsage(fullUsage), mParent(parent) {
31}
32
33HidTreeNode::HidTreeNode(std::shared_ptr<HidTreeNode> parent,
34                         uint32_t data, uint32_t fullUsage)
35        : mNodeType(TYPE_NORMAL), mData(data),
36        mFullUsage(fullUsage), mParent(parent) {
37}
38
39void HidTreeNode::outputRecursive(std::ostream &os, int level) const {
40    insertIndentation(os, level);
41    os << "Node data: " << mData
42       << ", usage " << std::hex << mFullUsage << std::dec << LOG_ENDL;
43
44    for (auto &child : mChildren) {
45        child->outputRecursive(os, level + 1);
46    }
47}
48
49std::shared_ptr<HidTreeNode> HidTreeNode::deepCopy(
50        std::shared_ptr<HidTreeNode> parent) const {
51    std::shared_ptr<HidTreeNode> copy(new HidTreeNode(parent, mData, mFullUsage, mNodeType));
52    for (auto &i : mChildren) {
53        copy->mChildren.push_back(i->deepCopy(copy));
54    }
55    return copy;
56}
57
58void HidTreeNode::insertIndentation(std::ostream &os, int level) const {
59    constexpr char indentCharacter = '\t';
60    std::fill_n(std::ostreambuf_iterator<char>(os), level, indentCharacter);
61}
62
63std::shared_ptr<HidTreeNode> HidTreeNode::addChild(std::shared_ptr<HidTreeNode> child) {
64    mChildren.push_back(child);
65    return child;
66}
67
68std::shared_ptr<HidTreeNode> HidTreeNode::getParent() const {
69    return mParent.lock();
70}
71
72bool HidTreeNode::isReportCollection() const {
73    return mNodeType == TYPE_NORMAL && mChildren.size() == 1
74            && mChildren.front()->mNodeType == TYPE_REPORT;
75}
76
77unsigned int HidTreeNode::getFullUsage() const {
78    return mFullUsage;
79}
80
81std::vector<std::shared_ptr<HidTreeNode>>& HidTreeNode::getChildren() {
82    return mChildren;
83}
84
85const std::vector<std::shared_ptr<HidTreeNode>>& HidTreeNode::getChildren() const {
86    return mChildren;
87}
88
89bool HidTreeNode::isUsageCollection() const {
90    using namespace HidDef::CollectionType;
91    return mNodeType == TYPE_NORMAL && (mData == PHYSICAL || mData == APPLICATION);
92}
93
94int HidTreeNode::getNodeType() const {
95    return mNodeType;
96}
97
98std::ostream& operator<<(std::ostream& os, const HidTreeNode& n) {
99    n.outputRecursive(os, 0);
100    return os;
101}
102
103// HidReportNode
104HidReportNode::HidReportNode(std::shared_ptr<HidTreeNode> parent, const HidReport &report)
105    : HidTreeNode(parent, 0 /*data*/, 0 /*fullUsage*/, TYPE_REPORT), mReport(report) {
106}
107
108void HidReportNode::outputRecursive(std::ostream &os, int level) const {
109    insertIndentation(os, level);
110    os << mReport << LOG_ENDL;
111}
112
113std::shared_ptr<HidTreeNode> HidReportNode::deepCopy(
114        std::shared_ptr<HidTreeNode> parent) const {
115    std::shared_ptr<HidTreeNode> copy(new HidReportNode(parent, mReport));
116    return copy;
117}
118
119const HidReport& HidReportNode::getReport() const {
120    return mReport;
121}
122
123void HidReportNode::collapse(unsigned int newUsage) {
124    mReport.setCollapsed(newUsage);
125}
126
127} //namespace HidUtil
128