1/*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef BLUETOOTH_OBSERVER_MAP_H
17#define BLUETOOTH_OBSERVER_MAP_H
18
19#include <functional>
20#include <map>
21#include <memory>
22#include <mutex>
23
24template <typename T>
25class BluetoothObserverMap final {
26public:
27    BluetoothObserverMap() = default;
28    ~BluetoothObserverMap();
29
30    bool Register(int handle, T observer);
31    bool Deregister(T observer);
32
33    void ForEach(const std::function<void(uint8_t, T)> &observer, int handle);
34
35    uint8_t GetAdvertiserHandle(T observer);
36    T PopAdvertiserObserver(uint8_t advHandle);
37    T GetAdvertiserObserver(uint8_t advHandle);
38    bool IsExistAdvertiserCallback(T observer, int &handle);
39    void Clear(void);
40
41private:
42    std::mutex lock_;
43    std::map<int, T> observers_;
44
45    BLUETOOTH_DISALLOW_COPY_AND_ASSIGN(BluetoothObserverMap);
46};
47
48template<typename T>
49void BluetoothObserverMap<T>::Clear(void)
50{
51    std::lock_guard<std::mutex> lock(lock_);
52    observers_.clear();
53}
54
55template<typename T>
56BluetoothObserverMap<T>::~BluetoothObserverMap()
57{
58    std::lock_guard<std::mutex> lock(lock_);
59    observers_.clear();
60}
61
62template<typename T>
63bool BluetoothObserverMap<T>::Register(int handle, T observer)
64{
65    std::lock_guard<std::mutex> lock(lock_);
66
67    auto it = observers_.begin();
68    for (; it != observers_.end();) {
69        if (it->first == handle) {
70            observers_.erase(it++);
71            observers_.insert(std::make_pair(handle, observer));
72            return true;
73        } else {
74            ++it;
75        }
76    }
77    if (it == observers_.end()) {
78        observers_.insert(std::make_pair(handle, observer));
79    }
80    return true;
81}
82
83template<typename T>
84bool BluetoothObserverMap<T>::Deregister(T observer)
85{
86    std::lock_guard<std::mutex> lock(lock_);
87    auto it = observers_.begin();
88    for (; it != observers_.end();) {
89        if (it->second == observer) {
90            observers_.erase(it++);
91            return true;
92        } else {
93            ++it;
94        }
95    }
96
97    return false;
98}
99
100template<typename T>
101void BluetoothObserverMap<T>::ForEach(const std::function<void(uint8_t, T)> &observer, int handle)
102{
103    std::lock_guard<std::mutex> lock(lock_);
104    for (const auto &it : observers_) {
105        if (handle == it.first) {
106            observer(it.first, it.second);
107        }
108    }
109}
110
111template<typename T>
112uint8_t BluetoothObserverMap<T>::GetAdvertiserHandle(T observer)
113{
114    std::lock_guard<std::mutex> lock(lock_);
115    uint8_t advHandle = OHOS::bluetooth::BLE_INVALID_ADVERTISING_HANDLE;
116    if (observer == nullptr) {
117        return advHandle;
118    }
119
120    auto it = observers_.begin();
121    for (; it != observers_.end(); it++) {
122        if (it->second == observer) {
123            advHandle = it->first;
124            break;
125        }
126    }
127
128    return advHandle;
129}
130
131template<typename T>
132T BluetoothObserverMap<T>::PopAdvertiserObserver(uint8_t advHandle)
133{
134    std::lock_guard<std::mutex> lock(lock_);
135    T t = nullptr;
136    auto it = observers_.begin();
137    for (; it != observers_.end(); it++) {
138        if (it->first == advHandle) {
139            t = it->second;
140            observers_.erase(it++);
141            break;
142        }
143    }
144    return t;
145}
146
147template<typename T>
148T BluetoothObserverMap<T>::GetAdvertiserObserver(uint8_t advHandle)
149{
150    std::lock_guard<std::mutex> lock(lock_);
151    auto it = observers_.begin();
152    for (; it != observers_.end(); it++) {
153        if (it->first == advHandle) {
154            return it->second;
155        }
156    }
157
158    return nullptr;
159}
160
161template<typename T>
162bool BluetoothObserverMap<T>::IsExistAdvertiserCallback(T observer, int &handle)
163{
164    bool isExtist = false;
165    if (observer == nullptr) {
166        return isExtist;
167    }
168
169    std::lock_guard<std::mutex> lock(lock_);
170    auto it = observers_.begin();
171    for (; it != observers_.end(); it++) {
172        if (it->second == observer) {
173            handle = it->first;
174            isExtist = true;
175            break;
176        }
177    }
178
179    return isExtist;
180}
181
182#endif  // BLUETOOTH_OBSERVER_LIST_H