Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/NimBLE2904.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct NimBLE2904Data {
*/
class NimBLE2904 : public NimBLEDescriptor {
public:
NimBLE2904(NimBLECharacteristic* pChr = nullptr);
explicit NimBLE2904(NimBLECharacteristic* pChr = nullptr);
static const uint8_t FORMAT_BOOLEAN = 1;
static const uint8_t FORMAT_UINT2 = 2;
static const uint8_t FORMAT_UINT4 = 3;
Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class NimBLEAddress : private ble_addr_t {
* @brief Create a blank address, i.e. 00:00:00:00:00:00, type 0.
*/
NimBLEAddress() = default;
NimBLEAddress(const ble_addr_t address);
NimBLEAddress(const uint8_t address[BLE_DEV_ADDR_LEN], uint8_t type);
NimBLEAddress(const std::string& stringAddress, uint8_t type);
NimBLEAddress(const uint64_t& address, uint8_t type);
explicit NimBLEAddress(const ble_addr_t address);

bool isRpa() const;
bool isNrpa() const;
Expand Down
6 changes: 3 additions & 3 deletions src/NimBLEAttValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class NimBLEAttValue {
* @param[in] init_len The initial size in bytes.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(uint16_t init_len = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH), uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
explicit NimBLEAttValue(uint16_t init_len = MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_INIT_LENGTH), uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);

/**
* @brief Construct with an initial value from a buffer.
Expand Down Expand Up @@ -206,15 +206,15 @@ class NimBLEAttValue {
* @param str A std::string containing to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const std::string str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
NimBLEAttValue(const std::string& str, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
: NimBLEAttValue(reinterpret_cast<const uint8_t*>(&str[0]), str.length(), max_len) {}

/**
* @brief Construct with an initial value from a std::vector<uint8_t>.
* @param vec A std::vector<uint8_t> containing to the initial value to set.
* @param[in] max_len The max size in bytes that the value can be.
*/
NimBLEAttValue(const std::vector<uint8_t> vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
NimBLEAttValue(const std::vector<uint8_t>& vec, uint16_t max_len = BLE_ATT_ATTR_MAX_LEN)
: NimBLEAttValue(&vec[0], vec.size(), max_len) {}

# if NIMBLE_CPP_ARDUINO_STRING_AVAILABLE
Expand Down
16 changes: 8 additions & 8 deletions src/NimBLECharacteristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ class NimBLE2904;
*/
class NimBLECharacteristic : public NimBLELocalValueAttribute {
public:
NimBLECharacteristic(const char* uuid,
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);
NimBLECharacteristic(const NimBLEUUID& uuid,
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);
explicit NimBLECharacteristic(const char* uuid,
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);
explicit NimBLECharacteristic(const NimBLEUUID& uuid,
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
NimBLEService* pService = nullptr);

~NimBLECharacteristic();

Expand Down
4 changes: 2 additions & 2 deletions src/NimBLEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,11 +1017,11 @@ int NimBLEClient::handleGapEvent(struct ble_gap_event* event, void* arg) {
// workaround for bug in NimBLE stack where disconnect event argument is not passed correctly
pClient = NimBLEDevice::getClientByHandle(event->disconnect.conn.conn_handle);
if (pClient == nullptr) {
pClient = NimBLEDevice::getClientByPeerAddress(event->disconnect.conn.peer_ota_addr);
pClient = NimBLEDevice::getClientByPeerAddress(NimBLEAddress(event->disconnect.conn.peer_ota_addr));
}

if (pClient == nullptr) {
pClient = NimBLEDevice::getClientByPeerAddress(event->disconnect.conn.peer_id_addr);
pClient = NimBLEDevice::getClientByPeerAddress(NimBLEAddress(event->disconnect.conn.peer_id_addr));
}

if (pClient == nullptr) {
Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class NimBLEClient {
private:
enum ConnStatus : uint8_t { CONNECTED, DISCONNECTED, CONNECTING, DISCONNECTING };

NimBLEClient(const NimBLEAddress& peerAddress);
explicit NimBLEClient(const NimBLEAddress& peerAddress);
~NimBLEClient();
NimBLEClient(const NimBLEClient&) = delete;
NimBLEClient& operator=(const NimBLEClient&) = delete;
Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEConnInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class NimBLEConnInfo {

ble_gap_conn_desc m_desc{};
NimBLEConnInfo() {};
NimBLEConnInfo(ble_gap_conn_desc desc) { m_desc = desc; }
explicit NimBLEConnInfo(ble_gap_conn_desc desc) : m_desc(desc) {}
};

#endif // NIMBLE_CPP_CONNINFO_H_
2 changes: 1 addition & 1 deletion src/NimBLEExtAdvertising.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class NimBLEUUID;
*/
class NimBLEExtAdvertisement {
public:
NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M, uint8_t secPhy = BLE_HCI_LE_PHY_1M);
explicit NimBLEExtAdvertisement(uint8_t priPhy = BLE_HCI_LE_PHY_1M, uint8_t secPhy = BLE_HCI_LE_PHY_1M);
bool setAppearance(uint16_t appearance);
bool addServiceUUID(const NimBLEUUID& serviceUUID);
bool addServiceUUID(const char* serviceUUID);
Expand Down
46 changes: 23 additions & 23 deletions src/NimBLEHIDDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,23 @@ static constexpr uint16_t bootOutputChrUuid = 0x2a32;
*/
NimBLEHIDDevice::NimBLEHIDDevice(NimBLEServer* server) {
// Here we create mandatory services described in bluetooth specification
m_deviceInfoSvc = server->createService(deviceInfoSvcUuid);
m_hidSvc = server->createService(hidSvcUuid);
m_batterySvc = server->createService(batterySvcUuid);
m_deviceInfoSvc = server->createService(NimBLEUUID(deviceInfoSvcUuid));
m_hidSvc = server->createService(NimBLEUUID(hidSvcUuid));
m_batterySvc = server->createService(NimBLEUUID(batterySvcUuid));

// Mandatory characteristic for device info service
m_pnpChr = m_deviceInfoSvc->createCharacteristic(pnpCharUuid, NIMBLE_PROPERTY::READ);
m_pnpChr = m_deviceInfoSvc->createCharacteristic(NimBLEUUID(pnpCharUuid), NIMBLE_PROPERTY::READ);

// Mandatory characteristics for HID service
m_hidInfoChr = m_hidSvc->createCharacteristic(hidInfoCharUuid, NIMBLE_PROPERTY::READ);
m_reportMapChr = m_hidSvc->createCharacteristic(reportMapCharUuid, NIMBLE_PROPERTY::READ);
m_hidControlChr = m_hidSvc->createCharacteristic(hidControlCharUuid, NIMBLE_PROPERTY::WRITE_NR);
m_hidInfoChr = m_hidSvc->createCharacteristic(NimBLEUUID(hidInfoCharUuid), NIMBLE_PROPERTY::READ);
m_reportMapChr = m_hidSvc->createCharacteristic(NimBLEUUID(reportMapCharUuid), NIMBLE_PROPERTY::READ);
m_hidControlChr = m_hidSvc->createCharacteristic(NimBLEUUID(hidControlCharUuid), NIMBLE_PROPERTY::WRITE_NR);
m_protocolModeChr =
m_hidSvc->createCharacteristic(protocolModeCharUuid, NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ);
m_hidSvc->createCharacteristic(NimBLEUUID(protocolModeCharUuid), NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::READ);

// Mandatory battery level characteristic with notification and presence descriptor
m_batteryLevelChr =
m_batterySvc->createCharacteristic(batteryLevelCharUuid, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
m_batterySvc->createCharacteristic(NimBLEUUID(batteryLevelCharUuid), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
NimBLE2904* batteryLevelDescriptor = m_batteryLevelChr->create2904();
batteryLevelDescriptor->setFormat(NimBLE2904::FORMAT_UINT8);
batteryLevelDescriptor->setUnit(0x27ad); // percentage
Expand Down Expand Up @@ -94,7 +94,7 @@ void NimBLEHIDDevice::startServices() {
*/
bool NimBLEHIDDevice::setManufacturer(const std::string& name) {
if (m_manufacturerChr == nullptr) {
m_manufacturerChr = m_deviceInfoSvc->createCharacteristic(m_manufacturerChrUuid, NIMBLE_PROPERTY::READ);
m_manufacturerChr = m_deviceInfoSvc->createCharacteristic(NimBLEUUID(m_manufacturerChrUuid), NIMBLE_PROPERTY::READ);
}

if (m_manufacturerChr) {
Expand Down Expand Up @@ -155,13 +155,13 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) {
* @return nullptr If the characteristic does not exist.
*/
NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicByIdAndType(uint8_t reportId, uint8_t reportType) {
NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, 0);
NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(NimBLEUUID(inputReportChrUuid), 0);
for (uint16_t i = 1; (candidate != nullptr) && (i != 0); i++) {
NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid);
NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(NimBLEUUID(featureReportDscUuid));
NimBLEAttValue desc1_val_att = dsc->getValue();
const uint8_t* desc1_val = desc1_val_att.data();
if ((desc1_val[0] == reportId) && (desc1_val[1] == reportType)) return candidate;
candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, i);
candidate = m_hidSvc->getCharacteristic(NimBLEUUID(inputReportChrUuid), i);
}
return nullptr;
}
Expand All @@ -177,10 +177,10 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
NimBLECharacteristic* inputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x01);
if (inputReportChr == nullptr) {
inputReportChr =
m_hidSvc->createCharacteristic(inputReportChrUuid,
m_hidSvc->createCharacteristic(NimBLEUUID(inputReportChrUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ_ENC);
NimBLEDescriptor* inputReportDsc =
inputReportChr->createDescriptor(featureReportDscUuid, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);
inputReportChr->createDescriptor(NimBLEUUID(featureReportDscUuid), NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_ENC);

uint8_t desc1_val[] = {reportId, 0x01};
inputReportDsc->setValue(desc1_val, 2);
Expand All @@ -200,11 +200,11 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
NimBLECharacteristic* outputReportChr = locateReportCharacteristicByIdAndType(reportId, 0x02);
if (outputReportChr == nullptr) {
outputReportChr =
m_hidSvc->createCharacteristic(inputReportChrUuid,
m_hidSvc->createCharacteristic(NimBLEUUID(inputReportChrUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR |
NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
NimBLEDescriptor* outputReportDsc = outputReportChr->createDescriptor(
featureReportDscUuid,
NimBLEUUID(featureReportDscUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
uint8_t desc1_val[] = {reportId, 0x02};
outputReportDsc->setValue(desc1_val, 2);
Expand All @@ -224,10 +224,10 @@ NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) {
NimBLECharacteristic* featureReportChr = locateReportCharacteristicByIdAndType(reportId, 0x03);
if (featureReportChr == nullptr) {
featureReportChr = m_hidSvc->createCharacteristic(
inputReportChrUuid,
NimBLEUUID(inputReportChrUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
NimBLEDescriptor* featureReportDsc = featureReportChr->createDescriptor(
featureReportDscUuid,
NimBLEUUID(featureReportDscUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);

uint8_t desc1_val[] = {reportId, 0x03};
Expand All @@ -243,12 +243,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) {
* @details This will create the characteristic if not already created.
*/
NimBLECharacteristic* NimBLEHIDDevice::getBootInput() {
NimBLECharacteristic* bootInputChr = m_hidSvc->getCharacteristic(bootInputChrUuid);
NimBLECharacteristic* bootInputChr = m_hidSvc->getCharacteristic(NimBLEUUID(bootInputChrUuid));
if (bootInputChr) {
return bootInputChr;
}

return m_hidSvc->createCharacteristic(bootInputChrUuid, NIMBLE_PROPERTY::NOTIFY);
return m_hidSvc->createCharacteristic(NimBLEUUID(bootInputChrUuid), NIMBLE_PROPERTY::NOTIFY);
} // getBootInput

/**
Expand All @@ -257,12 +257,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getBootInput() {
* @details This will create the characteristic if not already created.
*/
NimBLECharacteristic* NimBLEHIDDevice::getBootOutput() {
NimBLECharacteristic* bootOutputChr = m_hidSvc->getCharacteristic(bootOutputChrUuid);
NimBLECharacteristic* bootOutputChr = m_hidSvc->getCharacteristic(NimBLEUUID(bootOutputChrUuid));
if (bootOutputChr) {
return bootOutputChr;
}

return m_hidSvc->createCharacteristic(bootOutputChrUuid,
return m_hidSvc->createCharacteristic(NimBLEUUID(bootOutputChrUuid),
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_NR);
} // getBootOutput

Expand Down
2 changes: 1 addition & 1 deletion src/NimBLEHIDDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class NimBLECharacteristic;
*/
class NimBLEHIDDevice {
public:
NimBLEHIDDevice(NimBLEServer* server);
explicit NimBLEHIDDevice(NimBLEServer* server);

void setReportMap(uint8_t* map, uint16_t);
void startServices() __attribute__((deprecated("Services are now started by the server when start() is called, "
Expand Down
20 changes: 19 additions & 1 deletion src/NimBLERemoteService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static const char* LOG_TAG = "NimBLERemoteService";
* @param [in] service A pointer to the structure with the service information.
*/
NimBLERemoteService::NimBLERemoteService(NimBLEClient* pClient, const ble_gatt_svc* service)
: NimBLEAttribute{service->uuid, service->start_handle}, m_pClient{pClient}, m_endHandle{service->end_handle} {}
: NimBLEAttribute{NimBLEUUID(service->uuid), service->start_handle}, m_pClient{pClient}, m_endHandle{service->end_handle} {}

/**
* @brief When deleting the service make sure we delete all characteristics and descriptors.
Expand Down Expand Up @@ -64,6 +64,24 @@ std::vector<NimBLERemoteCharacteristic*>::iterator NimBLERemoteService::end() co
* @param [in] uuid Remote characteristic uuid.
* @return A pointer to the remote characteristic object.
*/
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(uint16_t uuid) const {
return getCharacteristic(NimBLEUUID(uuid));
} // getCharacteristic

/**
* @brief Get the remote characteristic object for the characteristic's 32-bit UUID.
* @param [in] uuid Remote characteristic 32-bit UUID.
* @return A pointer to the remote characteristic object.
*/
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(uint32_t uuid) const {
return getCharacteristic(NimBLEUUID(uuid));
} // getCharacteristic

/**
* @brief Get the remote characteristic object for the characteristic UUID.
* @param [in] uuid Remote characteristic 16-bit UUID.
* @return A pointer to the remote characteristic object.
*/
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* uuid) const {
return getCharacteristic(NimBLEUUID(uuid));
} // getCharacteristic
Expand Down
2 changes: 2 additions & 0 deletions src/NimBLERemoteService.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class NimBLEAttValue;
*/
class NimBLERemoteService : public NimBLEAttribute {
public:
NimBLERemoteCharacteristic* getCharacteristic(uint16_t uuid) const;
NimBLERemoteCharacteristic* getCharacteristic(uint32_t uuid) const;
NimBLERemoteCharacteristic* getCharacteristic(const char* uuid) const;
NimBLERemoteCharacteristic* getCharacteristic(const NimBLEUUID& uuid) const;
void deleteCharacteristics() const;
Expand Down
2 changes: 1 addition & 1 deletion src/NimBLERemoteValueAttribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class NimBLERemoteValueAttribute : public NimBLEValueAttribute, public NimBLEAtt
/**
* @brief Construct a new NimBLERemoteValueAttribute object.
*/
NimBLERemoteValueAttribute(const ble_uuid_any_t& uuid, uint16_t handle) : NimBLEAttribute{uuid, handle} {}
NimBLERemoteValueAttribute(const ble_uuid_any_t& uuid, uint16_t handle) : NimBLEAttribute(NimBLEUUID(uuid), handle) {}

/**
* @brief Destroy the NimBLERemoteValueAttribute object.
Expand Down
20 changes: 20 additions & 0 deletions src/NimBLEService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,26 @@ void NimBLEService::removeCharacteristic(NimBLECharacteristic* pChar, bool delet
* @param idx The index of the characteristic to return (used when multiple characteristics have the same UUID).
* @return A pointer to the characteristic object or nullptr if not found.
*/
NimBLECharacteristic* NimBLEService::getCharacteristic(uint16_t uuid, uint16_t idx) const {
return getCharacteristic(NimBLEUUID(uuid), idx);
} // getCharacteristic

/**
* @brief Get a pointer to the characteristic object with the specified 32-bit UUID.
* @param [in] uuid The characteristic's 32-bit UUID.
* @param idx The index of the characteristic to return (used when multiple characteristics have the same UUID).
* @return A pointer to the characteristic object or nullptr if not found.
*/
NimBLECharacteristic* NimBLEService::getCharacteristic(uint32_t uuid, uint16_t idx) const {
return getCharacteristic(NimBLEUUID(uuid), idx);
} // getCharacteristic

/**
* @brief Get a pointer to the characteristic object with the specified UUID.
* @param [in] uuid The characteristic UUID string.
* @param idx The index of the characteristic to return (used when multiple characteristics have the same UUID).
* @return A pointer to the characteristic object or nullptr if not found.
*/
NimBLECharacteristic* NimBLEService::getCharacteristic(const char* uuid, uint16_t idx) const {
return getCharacteristic(NimBLEUUID(uuid), idx);
} // getCharacteristic
Expand Down
6 changes: 4 additions & 2 deletions src/NimBLEService.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class NimBLEService;
*/
class NimBLEService : public NimBLELocalAttribute {
public:
NimBLEService(const char* uuid);
NimBLEService(const NimBLEUUID& uuid);
explicit NimBLEService(const char* uuid);
explicit NimBLEService(const NimBLEUUID& uuid);
~NimBLEService();

NimBLEServer* getServer() const;
Expand All @@ -59,6 +59,8 @@ class NimBLEService : public NimBLELocalAttribute {
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
void addCharacteristic(NimBLECharacteristic* pCharacteristic);
void removeCharacteristic(NimBLECharacteristic* pCharacteristic, bool deleteChr = false);
NimBLECharacteristic* getCharacteristic(uint16_t uuid, uint16_t instanceId = 0) const;
NimBLECharacteristic* getCharacteristic(uint32_t uuid, uint16_t instanceId = 0) const;
NimBLECharacteristic* getCharacteristic(const char* uuid, uint16_t instanceId = 0) const;
NimBLECharacteristic* getCharacteristic(const NimBLEUUID& uuid, uint16_t instanceId = 0) const;
NimBLECharacteristic* getCharacteristicByHandle(uint16_t handle) const;
Expand Down
Loading
Loading