From 9a93f49d7576d15b3dcea0fe518f083553357463 Mon Sep 17 00:00:00 2001 From: fpagliughi Date: Mon, 10 Mar 2025 16:00:49 -0400 Subject: [PATCH] #540 Missing default argument in async_client changed constructor breaks code compatibility. Updated 'client' and 'create_options' construcotrs to agree with 'async_client' --- CHANGELOG.md | 3 + examples/async_publish.cpp | 3 +- fmt.sh | 5 +- include/mqtt/async_client.h | 165 ++++++++++++++++--------------- include/mqtt/client.h | 58 +++-------- include/mqtt/create_options.h | 46 +++++---- include/mqtt/event.h | 47 ++++----- include/mqtt/iasync_client.h | 20 ++-- include/mqtt/message.h | 16 +-- include/mqtt/properties.h | 14 +-- include/mqtt/subscribe_options.h | 6 +- include/mqtt/thread_queue.h | 33 +++---- include/mqtt/topic.h | 28 +++--- include/mqtt/topic_matcher.h | 2 +- src/client.cpp | 26 ++--- src/message.cpp | 3 +- test/unit/test_async_client.cpp | 3 +- test/unit/test_client.cpp | 6 +- 18 files changed, 213 insertions(+), 271 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b1d5ab..1e0e595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Upcoming Version 1.5.2 (unreleased) +- Synchronous `Client` constructors updated to use `persistence_type` and (just) `create_options` + - Restored compatiblity with `async_client` - [#537](https://github.com/eclipse-paho/paho.mqtt.cpp/issues/537) Fixed the Windows DLL build by exporting message::EMPTY_STR and message::EMPTY_BIN +- [#540](https://github.com/eclipse-paho/paho.mqtt.cpp/issues/537) Missing default argument in `async_client` changed constructor breaks code compatibility diff --git a/examples/async_publish.cpp b/examples/async_publish.cpp index ebe555f..ccb0b5a 100644 --- a/examples/async_publish.cpp +++ b/examples/async_publish.cpp @@ -46,7 +46,8 @@ using namespace std::chrono; const string DFLT_SERVER_URI{"mqtt://localhost:1883"}; const string CLIENT_ID{"paho_cpp_async_publish"}; -const string PERSIST_DIR{"./persist"}; + +const mqtt::persistence_type PERSIST_DIR{"./persist"}; const string TOPIC{"hello"}; diff --git a/fmt.sh b/fmt.sh index 86e0555..4710132 100755 --- a/fmt.sh +++ b/fmt.sh @@ -1,7 +1,8 @@ #!/bin/bash # -# Runs clang format over the whole project tree +# Runs clang format over the whole project tree, excluding +# the 'externals/' and 'build/' directories. # -find . -path './externals' -prune -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i +find . -type d \( -path './externals' -o -path './build' \) -prune -iname '*.h' -o -iname '*.cpp' | xargs clang-format -i diff --git a/include/mqtt/async_client.h b/include/mqtt/async_client.h index 999f3cc..627fb03 100644 --- a/include/mqtt/async_client.h +++ b/include/mqtt/async_client.h @@ -15,7 +15,7 @@ ///////////////////////////////////////////////////////////////////////////// /******************************************************************************* - * Copyright (c) 2013-2024 Frank Pagliughi + * Copyright (c) 2013-2025 Frank Pagliughi * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -65,18 +65,18 @@ namespace mqtt { #if defined(PAHO_MQTTPP_VERSIONS) /** The version number for the client library. */ -const uint32_t PAHO_MQTTPP_VERSION = 0x01050000; +const uint32_t PAHO_MQTTPP_VERSION = 0x01050002; /** The version string for the client library */ -const string PAHO_MQTTPP_VERSION_STR("Paho MQTT C++ (mqttpp) v. 1.5.0"); +const string PAHO_MQTTPP_VERSION_STR("Paho MQTT C++ (mqttpp) v. 1.5.2"); /** Copyright notice for the client library */ -const string PAHO_MQTTPP_COPYRIGHT("Copyright (c) 2013-2024 Frank Pagliughi"); +const string PAHO_MQTTPP_COPYRIGHT("Copyright (c) 2013-2025 Frank Pagliughi"); #else /** The version number for the client library. */ -const uint32_t VERSION = 0x01050000; +const uint32_t VERSION = 0x01050002; /** The version string for the client library */ -const string VERSION_STR("Paho MQTT C++ (mqttpp) v. 1.5.0"); +const string VERSION_STR("Paho MQTT C++ (mqttpp) v. 1.5.2"); /** Copyright notice for the client library */ -const string COPYRIGHT("Copyright (c) 2013-2024 Frank Pagliughi"); +const string COPYRIGHT("Copyright (c) 2013-2025 Frank Pagliughi"); #endif ///////////////////////////////////////////////////////////////////////////// @@ -106,7 +106,7 @@ const string COPYRIGHT("Copyright (c) 2013-2024 Frank Pagliughi"); * the server, but return immediately, before a response is received back * from the server. * - * These methods return a `Token` to the caller which is akin to a C++ + * These methods return a `token` to the caller which is akin to a C++ * std::future. The caller can keep the Token, then use it later to block * until the asynchronous operation is complete and retrieve the result of * the operation, including any response from the server. @@ -116,6 +116,22 @@ const string COPYRIGHT("Copyright (c) 2013-2024 Frank Pagliughi"); * architecture, but is more complex in that it forces the user to avoid any * blocking operations and manually handle thread synchronization (since * the callbacks run in a separate thread managed by the library). + * + * Note that the numerous constructors pre-date the current, expansive, + * `create_options` structure. For a full set of create options, a + * builder can be used to specify the full set of options, then construct + * the client with those options, like this: + * + * @code + * auto createOpts = mqtt::create_options_builder() + * .server_uri(serverURI) + * .send_while_disconnected() + * .max_buffered_messages(25) + * .delete_oldest_messages() + * .finalize(); + * + * mqtt::async_client cli(createOpts); + * @endcode */ class async_client : public virtual iasync_client { @@ -221,24 +237,12 @@ public: * as a URI. * @param clientId a client identifier that is unique on the server * being connected to - * @throw exception if an argument is invalid - */ - explicit async_client(const string& serverURI, const string& clientId = string{}) - : async_client(serverURI, clientId, NO_PERSISTENCE) {} - /** - * Create an async_client that can be used to communicate with an MQTT - * server. - * This allows the caller to specify a user-defined persistence object, - * or use no persistence. - * @param serverURI the address of the server to connect to, specified - * as a URI. - * @param clientId a client identifier that is unique on the server - * being connected to * @param persistence The persistence that the client should use. * @throw exception if an argument is invalid */ - async_client( - const string& serverURI, const string& clientId, const persistence_type& persistence + explicit async_client( + const string& serverURI, const string& clientId = string{}, + const persistence_type& persistence = NO_PERSISTENCE ) : createOpts_{serverURI, clientId, persistence} { create(); @@ -258,7 +262,7 @@ public: */ async_client( const string& serverURI, const string& clientId, int maxBufferedMessages, - const persistence_type& persistence = persistence_type{} + const persistence_type& persistence = NO_PERSISTENCE ) : createOpts_{serverURI, clientId, maxBufferedMessages, persistence} { create(); @@ -277,7 +281,7 @@ public: */ async_client( const string& serverURI, const string& clientId, const create_options& opts, - const persistence_type& persistence + const persistence_type& persistence = NO_PERSISTENCE ) : createOpts_{serverURI, clientId, opts, persistence} { create(); @@ -368,8 +372,9 @@ public: * @throw exception for non security related problems * @throw security_exception for security related problems */ - token_ptr connect(connect_options options, void* userContext, iaction_listener& cb) - override; + token_ptr connect( + connect_options options, void* userContext, iaction_listener& cb + ) override; /** * * @param userContext optional object used to pass context to the @@ -542,7 +547,7 @@ public: */ delivery_token_ptr publish( string_ref topic, const void* payload, size_t n, int qos, bool retained, - const properties &props=properties() + const properties& props = properties() ) override; /** * Publishes a message to a topic on the server @@ -568,10 +573,10 @@ public: * @return token used to track and wait for the publish to complete. The * token will be passed to callback methods if set. */ - delivery_token_ptr publish(string_ref topic, binary_ref payload, int qos, bool retained, - const properties &props=properties() - ) - override; + delivery_token_ptr publish( + string_ref topic, binary_ref payload, int qos, bool retained, + const properties& props = properties() + ) override; /** * Publishes a message to a topic on the server * @param topic The topic to deliver the message to @@ -623,8 +628,9 @@ public: * @return token used to track and wait for the publish to complete. The * token will be passed to callback methods if set. */ - delivery_token_ptr publish(const_message_ptr msg, void* userContext, iaction_listener& cb) - override; + delivery_token_ptr publish( + const_message_ptr msg, void* userContext, iaction_listener& cb + ) override; /** * Subscribe to a topic, which may include wildcards. * @param topicFilter the topic to subscribe to, which can include @@ -712,8 +718,9 @@ public: * @return token Used to track and wait for the unsubscribe to complete. * The token will be passed to callback methods if set. */ - token_ptr unsubscribe(const string& topicFilter, const properties& props = properties()) - override; + token_ptr unsubscribe( + const string& topicFilter, const properties& props = properties() + ) override; /** * Requests the server unsubscribe the client from one or more topics. * @param topicFilters One or more topics to unsubscribe from. Each @@ -792,7 +799,8 @@ public: * This clears the consumer queue, discarding any pending event. */ void clear_consumer() override { - if (que_) que_->clear(); + if (que_) + que_->clear(); } /** * Determines if the consumer queue has been closed. @@ -801,9 +809,7 @@ public: * @return @true if the consumer queue has been closed, @false * otherwise. */ - bool consumer_closed() noexcept override { - return !que_ || que_->closed(); - } + bool consumer_closed() noexcept override { return !que_ || que_->closed(); } /** * Determines if the consumer queue is "done" (closed and empty). * Once the queue is done, no more events can be added or removed fom @@ -811,9 +817,7 @@ public: * @return @true if the consumer queue is closed and empty, @false * otherwise. */ - bool consumer_done() noexcept override { - return !que_ || que_->done(); - } + bool consumer_done() noexcept override { return !que_ || que_->done(); } /** * Gets the number of events available for immediate consumption. * Note that this retrieves the number of "raw" events, not messages, @@ -822,9 +826,7 @@ public: * as the event count may change between checking the size and actual retrieval. * @return the number of events in the queue. */ - std::size_t consumer_queue_size() const override { - return (que_) ? que_->size() : 0; - } + std::size_t consumer_queue_size() const override { return (que_) ? que_->size() : 0; } /** * Read the next client event from the queue. * This blocks until a new message arrives. @@ -835,8 +837,8 @@ public: /** * Try to read the next client event without blocking. * @param evt Pointer to the value to receive the event - * @return @em true if an event was read, @em false if no - * event was available. + * @return @em true if an event was read, @em false if no + * event was available. */ bool try_consume_event(event* evt) override; /** @@ -863,9 +865,9 @@ public: } /** * Waits a limited time for a client event to arrive. - * @param relTime The maximum amount of time to wait for an event. - * @return The event that was received. It will contain empty message on - * timeout. + * @param relTime The maximum amount of time to wait for an event. + * @return The event that was received. It will contain empty message on + * timeout. */ template event try_consume_event_for(const std::chrono::duration& relTime) { @@ -882,8 +884,8 @@ public: * Waits until a specific time for a client event to appear. * @param evt Pointer to the value to receive the event. * @param absTime The time point to wait until, before timing out. - * @return @em true if an event was recceived, @em false if a timeout - * occurred. + * @return @em true if an event was recceived, @em false if a timeout + * occurred. */ template bool try_consume_event_until( @@ -902,13 +904,12 @@ public: } /** * Waits until a specific time for a client event to appear. - * @param absTime The time point to wait until, before timing out. - * @return The event that was received. It will contain empty message on - * timeout. + * @param absTime The time point to wait until, before timing out. + * @return The event that was received. It will contain empty message on + * timeout. */ template - event try_consume_event_until(const std::chrono::time_point& absTime - ) { + event try_consume_event_until(const std::chrono::time_point& absTime) { event evt; try { que_->try_get_until(&evt, absTime); @@ -948,20 +949,20 @@ public: event evt; - while (true) { - if (!try_consume_event_for(&evt, relTime)) - return false; + while (true) { + if (!try_consume_event_for(&evt, relTime)) + return false; - if (const auto* pval = evt.get_message_if()) { - *msg = std::move(*pval); - break; - } + if (const auto* pval = evt.get_message_if()) { + *msg = std::move(*pval); + break; + } - if (evt.is_any_disconnect()) { - *msg = const_message_ptr{}; - break; - } - } + if (evt.is_any_disconnect()) { + *msg = const_message_ptr{}; + break; + } + } return true; } /** @@ -994,20 +995,20 @@ public: event evt; - while (true) { - if (!try_consume_event_until(&evt, absTime)) - return false; + while (true) { + if (!try_consume_event_until(&evt, absTime)) + return false; - if (const auto* pval = evt.get_message_if()) { - *msg = std::move(*pval); - break; - } + if (const auto* pval = evt.get_message_if()) { + *msg = std::move(*pval); + break; + } - if (!evt.is_any_disconnect()) { - *msg = const_message_ptr{}; - break; - } - } + if (!evt.is_any_disconnect()) { + *msg = const_message_ptr{}; + break; + } + } return true; } diff --git a/include/mqtt/client.h b/include/mqtt/client.h index 5dc1948..aea8865 100644 --- a/include/mqtt/client.h +++ b/include/mqtt/client.h @@ -99,30 +99,16 @@ public: /** * Create a client that can be used to communicate with an MQTT server. - * This allows the caller to specify a user-defined persistence object, - * or use no persistence. * @param serverURI the address of the server to connect to, specified * as a URI. * @param clientId a client identifier that is unique on the server - * being connected to - * @param persistence The user persistence structure. If this is null, - * then no persistence is used. + * being connected to. + * @param persistence The desired persistence type. */ client( - const string& serverURI, const string& clientId, - iclient_persistence* persistence = nullptr + const string& serverURI, const string& clientId = string{}, + const persistence_type& persistence = NO_PERSISTENCE ); - /** - * Create an async_client that can be used to communicate with an MQTT - * server. - * This uses file-based persistence in the specified directory. - * @param serverURI the address of the server to connect to, specified - * as a URI. - * @param clientId a client identifier that is unique on the server - * being connected to - * @param persistDir The directory to use for persistence data - */ - client(const string& serverURI, const string& clientId, const string& persistDir); /** * Create a client that can be used to communicate with an MQTT server, * which allows for off-line message buffering. @@ -134,46 +120,32 @@ public: * being connected to * @param maxBufferedMessages the maximum number of messages allowed to * be buffered while not connected - * @param persistence The user persistence structure. If this is null, - * then no persistence is used. + * @param persistence The desired persistence type. */ client( const string& serverURI, const string& clientId, int maxBufferedMessages, - iclient_persistence* persistence = nullptr + const persistence_type& persistence = NO_PERSISTENCE ); /** * Create a client that can be used to communicate with an MQTT server, - * which allows for off-line message buffering. - * This uses file-based persistence in the specified directory. - * @param serverURI the address of the server to connect to, specified - * as a URI. - * @param clientId a client identifier that is unique on the server - * being connected to - * @param maxBufferedMessages the maximum number of messages allowed to - * be buffered while not connected - * @param persistDir The directory to use for persistence data - */ - client( - const string& serverURI, const string& clientId, int maxBufferedMessages, - const string& persistDir - ); - /** - * Create an async_client that can be used to communicate with an MQTT - * server, which allows for off-line message buffering. - * This allows the caller to specify a user-defined persistence object, - * or use no persistence. + * which allows for off-line message buffering. This allows the caller + * to specify a user-defined persistence object, or use no persistence. * @param serverURI the address of the server to connect to, specified * as a URI. * @param clientId a client identifier that is unique on the server * being connected to * @param opts The create options - * @param persistence The user persistence structure. If this is null, - * then no persistence is used. + * @param persistence The desired persistence type. */ client( const string& serverURI, const string& clientId, const create_options& opts, - iclient_persistence* persistence = nullptr + const persistence_type& persistence = NO_PERSISTENCE ); + /** + * Create a client that can be used to communicate with an MQTT server. + * @param opts The create options + */ + client(const create_options& opts); /** * Virtual destructor */ diff --git a/include/mqtt/create_options.h b/include/mqtt/create_options.h index 7dfa0f0..39c1f04 100644 --- a/include/mqtt/create_options.h +++ b/include/mqtt/create_options.h @@ -6,7 +6,7 @@ ///////////////////////////////////////////////////////////////////////////// /******************************************************************************* - * Copyright (c) 2020-2024 Frank Pagliughi + * Copyright (c) 2020-2025 Frank Pagliughi * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -44,17 +44,34 @@ constexpr no_persistence NO_PERSISTENCE{}; /** * A variant for the different type of persistence: - * @li no_persistence: Any object of this type indicates no persistence. - * @li string: Indicates file persistence. The string specifies the + * @li @em no_persistence: Any object of this type indicates no persistence + * is desired. + * @li @em string: Indicates file persistence. The string specifies the * directory for the persistence store. - * @li iclient_persistence*: User-defined persistence + * @li @em iclient_persistence*: User-defined persistence */ using persistence_type = std::variant; ///////////////////////////////////////////////////////////////////////////// /** - * Options for creating a client object. + * The set of options for constructing a client object. + * + * Note that the numerous, incomplete set of constructors pre-date the + * current, expanded, options structure. For a full set of create options, a + * builder can be used to specify the options, then construct the client + * with those options, like this: + * + * @code + * auto createOpts = mqtt::create_options_builder() + * .server_uri(serverURI) + * .send_while_disconnected() + * .max_buffered_messages(25) + * .delete_oldest_messages() + * .finalize(); + * + * mqtt::async_client cli(createOpts); + * @endcode */ class create_options { @@ -98,18 +115,6 @@ public: * be buffered while not connected */ create_options(int mqttVersion, int maxBufferedMessages); - - /** - * Cretae options for the specified server and client ID. - * This uses file-based persistence in the specified directory. - * @param serverURI the address of the server to connect to, specified - * as a URI. - * @param clientId a client identifier that is unique on the server - * being connected to - * @throw exception if an argument is invalid - */ - explicit create_options(const string& serverURI, const string& clientId = string{}) - : serverURI_{serverURI}, clientId_{clientId} {} /** * Create options for the specified server and client ID, with optional * persistence. @@ -122,8 +127,9 @@ public: * @param persistence The desired persistence structure. * @throw exception if an argument is invalid */ - create_options( - const string& serverURI, const string& clientId, const persistence_type& persistence + explicit create_options( + const string& serverURI, const string& clientId = string{}, + const persistence_type& persistence = NO_PERSISTENCE ) : serverURI_{serverURI}, clientId_{clientId}, persistence_{persistence} {} /** @@ -141,7 +147,7 @@ public: */ create_options( const string& serverURI, const string& clientId, int maxBufferedMessages, - const persistence_type& persistence + const persistence_type& persistence = NO_PERSISTENCE ) : serverURI_{serverURI}, clientId_{clientId}, persistence_{persistence} { opts_.maxBufferedMessages = maxBufferedMessages; diff --git a/include/mqtt/event.h b/include/mqtt/event.h index bcb003c..4491077 100644 --- a/include/mqtt/event.h +++ b/include/mqtt/event.h @@ -24,11 +24,12 @@ #ifndef __mqtt_event_h #define __mqtt_event_h +#include + #include "mqtt/message.h" #include "mqtt/properties.h" #include "mqtt/reason_code.h" #include "mqtt/types.h" -#include namespace mqtt { @@ -54,8 +55,9 @@ struct disconnected_event }; /** Event for when the consumer queue is shutdown from another thread */ -struct shutdown_event { }; - +struct shutdown_event +{ +}; /* Event for when a message arrives is just a message pointer */ @@ -86,7 +88,8 @@ class event public: /** The variant type for any possible event. */ using event_type = std::variant< - const_message_ptr, connected_event, connection_lost_event, disconnected_event, shutdown_event>; + const_message_ptr, connected_event, connection_lost_event, disconnected_event, + shutdown_event>; private: event_type evt_{}; @@ -176,17 +179,13 @@ public: * @return @em true if this event is an incoming message, @em false * otherwise. */ - bool is_message() const { - return std::holds_alternative(evt_); - } + bool is_message() const { return std::holds_alternative(evt_); } /** * Determines if this event is a client (re)connection. * @return @em true if this event is a client connection, @em false * otherwise. */ - bool is_connected() const { - return std::holds_alternative(evt_); - } + bool is_connected() const { return std::holds_alternative(evt_); } /** * Determines if this event is a client connection lost. * @return @em true if this event is a client connection lost, @em false @@ -200,35 +199,29 @@ public: * @return @em true if this event is a client disconnected, @em false * otherwise. */ - bool is_disconnected() const { - return std::holds_alternative(evt_); - } + bool is_disconnected() const { return std::holds_alternative(evt_); } /** * Determines if this event is an internal shutdown request. * @return @em true if this event is a shutdown request, @em false * otherwise. */ - bool is_shutdown() const { - return std::holds_alternative(evt_); - } + bool is_shutdown() const { return std::holds_alternative(evt_); } /** * Determines if this is any type of client disconnect or shutdown. * @return @em true if this event is any type of client disconnect such * as a 'connection lost', 'disconnected', or shutdown event. */ bool is_any_disconnect() const { - return std::holds_alternative(evt_) - || std::holds_alternative(evt_) - || std::holds_alternative(evt_); + return std::holds_alternative(evt_) || + std::holds_alternative(evt_) || + std::holds_alternative(evt_); } /** * Gets the message from the event, iff this is a message event. * @return A message pointer, if this is a message event. * @throw std::bad_variant_access if this is not a 'message' event. */ - const_message_ptr get_message() { - return std::get(evt_); - } + const_message_ptr get_message() { return std::get(evt_); } /** * Gets the underlying information for a disconnected event iff this is * a 'disconnected' event. @@ -238,17 +231,14 @@ public: * why the server disconnected. * @throw std::bad_variant_access if this is not a 'disconnected' event. */ - disconnected_event get_disconnected() { - return std::get(evt_); - } + disconnected_event get_disconnected() { return std::get(evt_); } /** * Gets a pointer to the message in the event, iff this is a message * event. * @return A pointer to a message pointer, if this is a message event. * Returns nulltr if this is not a message event. */ - constexpr std::add_pointer_t - get_message_if() noexcept { + constexpr std::add_pointer_t get_message_if() noexcept { return std::get_if(&evt_); } /** @@ -260,8 +250,7 @@ public: * why the server disconnected. * @throw std::bad_variant_access if this is not a 'disconnected' event. */ - constexpr std::add_pointer_t - get_disconnected_if() noexcept { + constexpr std::add_pointer_t get_disconnected_if() noexcept { return std::get_if(&evt_); } }; diff --git a/include/mqtt/iasync_client.h b/include/mqtt/iasync_client.h index 46cc2fe..304f9e0 100644 --- a/include/mqtt/iasync_client.h +++ b/include/mqtt/iasync_client.h @@ -208,7 +208,7 @@ public: */ virtual delivery_token_ptr publish( string_ref topic, const void* payload, size_t n, int qos, bool retained, - const properties &props=properties() + const properties& props = properties() ) = 0; /** * Publishes a message to a topic on the server @@ -251,7 +251,7 @@ public: */ virtual delivery_token_ptr publish( string_ref topic, binary_ref payload, int qos, bool retained, - const properties &props=properties() + const properties& props = properties() ) = 0; /** * Publishes a message to a topic on the server. @@ -462,9 +462,7 @@ public: * @return @true if the consumer queue has been closed, @false * otherwise. */ - virtual bool consumer_closed() noexcept { - return false; - } + virtual bool consumer_closed() noexcept { return false; } /** * Determines if the consumer queue is "done" (closed and empty). * Once the queue is done, no more events can be added or removed fom @@ -472,9 +470,7 @@ public: * @return @true if the consumer queue is closed and empty, @false * otherwise. */ - virtual bool consumer_done() noexcept { - return false; - } + virtual bool consumer_done() noexcept { return false; } /** * Gets the number of events available for immediate consumption. * Note that this retrieves the number of "raw" events, not messages, @@ -502,14 +498,12 @@ public: * This blocks until a new message arrives. * @return The message and topic. */ - virtual event consume_event() { - return event{}; - } + virtual event consume_event() { return event{}; } /** * Try to read the next message from the queue without blocking. * @param evt Pointer to the value to receive the event - * @return @em true is an event was received, @em false if no event was - * available. + * @return @em true is an event was received, @em false if no event was + * available. */ virtual bool try_consume_event(event* evt) { (void)evt; diff --git a/include/mqtt/message.h b/include/mqtt/message.h index 5e529fa..9e81996 100644 --- a/include/mqtt/message.h +++ b/include/mqtt/message.h @@ -262,9 +262,7 @@ public: * Gets the topic for the message. * @return The topic string for the message. */ - const string& get_topic() const { - return topic_ ? topic_.str() : EMPTY_STR; - } + const string& get_topic() const { return topic_ ? topic_.str() : EMPTY_STR; } /** * Clears the payload, resetting it to be empty. */ @@ -276,15 +274,11 @@ public: /** * Gets the payload */ - const binary& get_payload() const { - return payload_ ? payload_.str() : EMPTY_BIN; - } + const binary& get_payload() const { return payload_ ? payload_.str() : EMPTY_BIN; } /** * Gets the payload as a string */ - const string& get_payload_str() const { - return payload_ ? payload_.str() : EMPTY_STR; - } + const string& get_payload_str() const { return payload_ ? payload_.str() : EMPTY_STR; } /** * Returns the quality of service for this message. * @return The quality of service for this message. @@ -389,7 +383,7 @@ using const_message_ptr = message::const_ptr_t; */ inline message_ptr make_message( string_ref topic, const void* payload, size_t len, int qos, bool retained, - const properties& props = properties() + const properties& props = properties() ) { return mqtt::message::create(std::move(topic), payload, len, qos, retained, props); } @@ -414,7 +408,7 @@ inline message_ptr make_message(string_ref topic, const void* payload, size_t le */ inline message_ptr make_message( string_ref topic, binary_ref payload, int qos, bool retained, - const properties& props = properties() + const properties& props = properties() ) { return mqtt::message::create(std::move(topic), std::move(payload), qos, retained, props); } diff --git a/include/mqtt/properties.h b/include/mqtt/properties.h index d60181c..bc13bed 100644 --- a/include/mqtt/properties.h +++ b/include/mqtt/properties.h @@ -31,10 +31,10 @@ extern "C" { #include #include #include +#include #include #include #include -#include #include "mqtt/buffer_ref.h" #include "mqtt/exception.h" @@ -410,9 +410,7 @@ public: * @param i The index * @return The property at the specified index. */ - const property operator[](size_t i) const { - return property{props_.array[i]}; - } + const property operator[](size_t i) const { return property{props_.array[i]}; } /** * Gets the property at the specified index in the collection. * @param i The index @@ -478,9 +476,11 @@ public: * @return The number of properties in the list with the specified ID. */ size_t count(property::code propid) const { - return size_t(::MQTTProperties_propertyCount( - const_cast(&props_), MQTTPropertyCodes(propid) - )); + return size_t( + ::MQTTProperties_propertyCount( + const_cast(&props_), MQTTPropertyCodes(propid) + ) + ); } /** * Gets the property with the specified ID. diff --git a/include/mqtt/subscribe_options.h b/include/mqtt/subscribe_options.h index 4e4b73a..14ff9f3 100644 --- a/include/mqtt/subscribe_options.h +++ b/include/mqtt/subscribe_options.h @@ -66,11 +66,9 @@ public: static constexpr bool LOCAL = false; /** @deprecated Don't receive our own publications */ - [[deprecated("Use NO_LOCAL")]] - static constexpr bool SUBSCRIBE_NO_LOCAL = true; + [[deprecated("Use NO_LOCAL")]] static constexpr bool SUBSCRIBE_NO_LOCAL = true; /** @deprecated Receive our own publications (obsolete name) */ - [[deprecated("Use LOCAL")]] - static constexpr bool SUBSCRIBE_LOCAL = false; + [[deprecated("Use LOCAL")]] static constexpr bool SUBSCRIBE_LOCAL = false; /** * Retain flag is only set on publications sent by a broker if in diff --git a/include/mqtt/thread_queue.h b/include/mqtt/thread_queue.h index 677209a..d05e473 100644 --- a/include/mqtt/thread_queue.h +++ b/include/mqtt/thread_queue.h @@ -116,9 +116,7 @@ private: using unique_guard = std::unique_lock; /** Checks if the queue is done (unsafe) */ - bool is_done() const { - return closed_ && que_.empty(); - } + bool is_done() const { return closed_ && que_.empty(); } public: /** @@ -207,8 +205,7 @@ public: */ void clear() { guard g{lock_}; - while (!que_.empty()) - que_.pop(); + while (!que_.empty()) que_.pop(); notFullCond_.notify_all(); } /** @@ -220,7 +217,8 @@ public: void put(value_type val) { unique_guard g{lock_}; notFullCond_.wait(g, [this] { return que_.size() < cap_ || closed_; }); - if (closed_) throw queue_closed{}; + if (closed_) + throw queue_closed{}; que_.emplace(std::move(val)); notEmptyCond_.notify_one(); @@ -252,10 +250,9 @@ public: template bool try_put_for(value_type val, const std::chrono::duration& relTime) { unique_guard g{lock_}; - bool to = !notFullCond_.wait_for( - g, relTime, - [this] { return que_.size() < cap_ || closed_; } - ); + bool to = !notFullCond_.wait_for(g, relTime, [this] { + return que_.size() < cap_ || closed_; + }); if (to || closed_) return false; @@ -278,10 +275,9 @@ public: value_type val, const std::chrono::time_point& absTime ) { unique_guard g{lock_}; - bool to = !notFullCond_.wait_until( - g, absTime, - [this] { return que_.size() < cap_ || closed_; } - ); + bool to = !notFullCond_.wait_until(g, absTime, [this] { + return que_.size() < cap_ || closed_; + }); if (to || closed_) return false; @@ -364,10 +360,7 @@ public: return false; unique_guard g{lock_}; - notEmptyCond_.wait_for( - g, relTime, - [this] { return !que_.empty() || closed_; } - ); + notEmptyCond_.wait_for(g, relTime, [this] { return !que_.empty() || closed_; }); if (que_.empty()) return false; @@ -395,9 +388,7 @@ public: return false; unique_guard g{lock_}; - notEmptyCond_.wait_until( - g, absTime, [this] { return !que_.empty() || closed_; } - ); + notEmptyCond_.wait_until(g, absTime, [this] { return !que_.empty() || closed_; }); if (que_.empty()) return false; diff --git a/include/mqtt/topic.h b/include/mqtt/topic.h index a9dbbd5..4e9034a 100644 --- a/include/mqtt/topic.h +++ b/include/mqtt/topic.h @@ -211,22 +211,18 @@ public: * '+' and '#'. */ explicit topic_filter(const string& filter); - /** - * Determins if the character is a wildcard, '+' or '#' - * @param c The character to check - * @return @em true if `c` is a wildcard, '+' or '#' - */ - static bool is_wildcard(char c) { - return c == '+' || c == '#'; - } - /** - * Determins if the string (field) is a wildcard, "+" or "#" - * @param s The string to check - * @return @em true if `c` is a wildcard, "+" or "#" - */ - static bool is_wildcard(const string& s) { - return s.size() == 1 && is_wildcard(s[0]); - } + /** + * Determins if the character is a wildcard, '+' or '#' + * @param c The character to check + * @return @em true if `c` is a wildcard, '+' or '#' + */ + static bool is_wildcard(char c) { return c == '+' || c == '#'; } + /** + * Determins if the string (field) is a wildcard, "+" or "#" + * @param s The string to check + * @return @em true if `c` is a wildcard, "+" or "#" + */ + static bool is_wildcard(const string& s) { return s.size() == 1 && is_wildcard(s[0]); } /** * Determines if the specified topic/filter contains any wildcards. * diff --git a/include/mqtt/topic_matcher.h b/include/mqtt/topic_matcher.h index 1a8d865..cd08f18 100644 --- a/include/mqtt/topic_matcher.h +++ b/include/mqtt/topic_matcher.h @@ -334,7 +334,7 @@ public: } // Topics starting with '$' don't match wildcards in the first field - // MQTT v5 Spec, Section 4.7.2: + // MQTT v5 Spec, Section 4.7.2: // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901246 if (!snode.first_ || field.empty() || field[0] != '$') { diff --git a/src/client.cpp b/src/client.cpp index 32b0107..b1409f7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2,7 +2,7 @@ // Implementation of the client class for the mqtt C++ client library. /******************************************************************************* - * Copyright (c) 2013-2017 Frank Pagliughi + * Copyright (c) 2013-2025 Frank Pagliughi * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -33,21 +33,16 @@ PAHO_MQTTPP_EXPORT const int client::DFLT_QOS = 1; // -------------------------------------------------------------------------- client::client( - const string& serverURI, const string& clientId, - iclient_persistence* persistence /*=nullptr*/ + const string& serverURI, const string& clientId /*=string{}*/, + const persistence_type& persistence /*=NO_PERSISTENCE*/ ) : cli_(serverURI, clientId, persistence), timeout_(DFLT_TIMEOUT), userCallback_(nullptr) { } -client::client(const string& serverURI, const string& clientId, const string& persistDir) - : cli_(serverURI, clientId, persistDir), timeout_(DFLT_TIMEOUT), userCallback_(nullptr) -{ -} - client::client( const string& serverURI, const string& clientId, int maxBufferedMessages, - iclient_persistence* persistence /*=nullptr*/ + const persistence_type& persistence /*=NO_PERSISTENCE*/ ) : cli_(serverURI, clientId, maxBufferedMessages, persistence), timeout_(DFLT_TIMEOUT), @@ -56,20 +51,17 @@ client::client( } client::client( - const string& serverURI, const string& clientId, int maxBufferedMessages, - const string& persistDir + const string& serverURI, const string& clientId, const create_options& opts, + const persistence_type& persistence /*=NO_PERSISTENCE*/ ) - : cli_(serverURI, clientId, maxBufferedMessages, persistDir), + : cli_(serverURI, clientId, opts, persistence), timeout_(DFLT_TIMEOUT), userCallback_(nullptr) { } -client::client( - const string& serverURI, const string& clientId, const create_options& opts, - iclient_persistence* persistence /*=nullptr*/ -) - : cli_(serverURI, clientId, opts, persistence), +client::client(const create_options& opts) + : cli_(opts), timeout_(DFLT_TIMEOUT), userCallback_(nullptr) { diff --git a/src/message.cpp b/src/message.cpp index dae5861..713b1bf 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -17,11 +17,12 @@ *******************************************************************************/ #include "mqtt/message.h" -#include "mqtt/export.h" #include #include +#include "mqtt/export.h" + namespace mqtt { // A const string to use for references diff --git a/test/unit/test_async_client.cpp b/test/unit/test_async_client.cpp index 4f6c9f9..dc19cbe 100644 --- a/test/unit/test_async_client.cpp +++ b/test/unit/test_async_client.cpp @@ -44,9 +44,10 @@ static const std::string GOOD_SSL_SERVER_URI{"ssl://localhost:18885"}; static const std::string BAD_SERVER_URI{"one://invalid.address"}; static const std::string CLIENT_ID{"test_async_client"}; -static const std::string PERSISTENCE_DIR{"persist"}; static const std::string TOPIC{"topic"}; +static const persistence_type PERSISTENCE_DIR{"persist"}; + static const int GOOD_QOS{0}; static const int BAD_QOS{3}; static const_string_collection_ptr TOPIC_COLL{ diff --git a/test/unit/test_client.cpp b/test/unit/test_client.cpp index c98969f..d39d5f6 100644 --- a/test/unit/test_client.cpp +++ b/test/unit/test_client.cpp @@ -4,7 +4,7 @@ // /******************************************************************************* - * Copyright (c) 2020-2024 Frank Pagliughi + * Copyright (c) 2020-2025 Frank Pagliughi * Copyright (c) 2017 Guilherme M. Ferreira * * All rights reserved. This program and the accompanying materials @@ -46,8 +46,10 @@ static const std::string GOOD_SERVER_URI{"tcp://localhost:1883"}; #endif static const std::string BAD_SERVER_URI{"one://invalid.address"}; static const std::string CLIENT_ID{"client_test"}; -static const std::string PERSISTENCE_DIR{"persist"}; static const std::string TOPIC{"TOPIC"}; + +static const persistence_type PERSISTENCE_DIR{"persist"}; + static const int GOOD_QOS{0}; static const int BAD_QOS{3};