From c1efe23ddfe1d297aa5c2cf4e165ea50667e48b4 Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Mon, 3 Jun 2013 15:30:55 +0100 Subject: [PATCH] Doxygen document updates --- doc/DoxyfileV3AsyncAPI | 4 +- doc/DoxyfileV3ClientAPI | 4 +- doc/DoxyfileV3ClientInternal | 4 +- src/Log.c | 7 + src/MQTTAsync.c | 7 + src/MQTTAsync.h | 130 +++++++++++++++++- src/MQTTClient.c | 6 + src/MQTTClient.h | 258 +++++++++++++++++++++++++---------- src/utf-8.c | 46 +++++-- 9 files changed, 372 insertions(+), 94 deletions(-) diff --git a/doc/DoxyfileV3AsyncAPI b/doc/DoxyfileV3AsyncAPI index 113e98ac..1fa4872d 100644 --- a/doc/DoxyfileV3AsyncAPI +++ b/doc/DoxyfileV3AsyncAPI @@ -545,7 +545,7 @@ GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = MQTTAsync_main # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in @@ -1520,7 +1520,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = __attribute__(x)= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/doc/DoxyfileV3ClientAPI b/doc/DoxyfileV3ClientAPI index b92e389a..25413c9b 100644 --- a/doc/DoxyfileV3ClientAPI +++ b/doc/DoxyfileV3ClientAPI @@ -545,7 +545,7 @@ GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = MQTTClient_main # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in @@ -1520,7 +1520,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = __attribute__(x)= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/doc/DoxyfileV3ClientInternal b/doc/DoxyfileV3ClientInternal index 9679105c..56faaaa8 100644 --- a/doc/DoxyfileV3ClientInternal +++ b/doc/DoxyfileV3ClientInternal @@ -26,7 +26,7 @@ DOXYFILE_ENCODING = UTF-8 # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. -PROJECT_NAME = "MQTT C Client" +PROJECT_NAME = "MQTT C Client Libraries Internals" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or @@ -545,7 +545,7 @@ GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. -ENABLED_SECTIONS = +ENABLED_SECTIONS = MQTTClient_internal # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in diff --git a/src/Log.c b/src/Log.c index 121dde78..04747679 100644 --- a/src/Log.c +++ b/src/Log.c @@ -15,6 +15,13 @@ * Ian Craggs - updates for the async client *******************************************************************************/ +/** + * @file + * \brief Logging and tracing module + * + * + */ + #include "Log.h" #include "MQTTPacket.h" #include "MQTTProtocol.h" diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index 6e24e222..5a947ed7 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -16,6 +16,13 @@ * Ian Craggs - multiple server connection support *******************************************************************************/ +/** + * @file + * \brief Asynchronous API implementation + * + */ + + #include #if !defined(WIN32) #include diff --git a/src/MQTTAsync.h b/src/MQTTAsync.h index 82ce52c8..4ec0a43b 100644 --- a/src/MQTTAsync.h +++ b/src/MQTTAsync.h @@ -19,7 +19,9 @@ /********************************************************************/ /** + * @cond MQTTAsync_main * @mainpage Asynchronous MQTT client library for C + * * © Copyright IBM Corp. 2009, 2013 * * @brief An Asynchronous MQTT client library for C. @@ -34,17 +36,16 @@ * API to the MQTT protocol using the programming language and platform of your * choice. This can be time-consuming and error-prone. * - * To simplify writing MQTT client applications, WebSphere MQ Telemetry provides - * C and Java client libraries that encapsulate the MQTT v3 protocol for a - * number of platforms. If you incorporate these libraries in your MQTT - * applications, a fully functional MQTT client can be written in a few lines of - * code. The information presented here documents the API provided by the IBM - * Asynchronous MQTT Client library for C. + * To simplify writing MQTT client applications, this library encapsulates + * the MQTT v3 protocol for you. Using this library enables a fully functional + * MQTT client application to be written in a few lines of code. + * The information presented here documents the API provided + * by the Asynchronous MQTT Client library for C. * * Using the client
* Applications that use the client library typically use a similar structure: *
    - *
  • Create a clent
  • + *
  • Create a client object
  • *
  • Set the options to connect to an MQTT server
  • *
  • Set up callback functions
  • *
  • Connect the client to an MQTT server
  • @@ -67,7 +68,9 @@ *
  • @ref async
  • *
  • @ref wildcard
  • *
  • @ref qos
  • + *
  • @ref tracing
  • *
+ * @endcond */ @@ -953,6 +956,7 @@ DLLExport MQTTAsync_nameValue* MQTTAsync_getVersionInfo(); /** + * @cond MQTTAsync_main * @page async Threading * The client application runs on several threads. * Processing of handshaking and maintaining @@ -1349,6 +1353,118 @@ exit: } * @endcode +* @page tracing Tracing + * + * Runtime tracing can be controlled by environment variables or API calls. + * + * #### Environment variables + * + * Tracing is switched on by setting the MQTT_C_CLIENT_TRACE environment variable. + * A value of ON, or stdout, prints to stdout, any other value is interpreted as a file name to use. + * + * The amount of trace detail is controlled with the MQTT_C_CLIENT_TRACE_LEVEL environment + * variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM + * (from least to most verbose). + * + * The variable MQTT_C_CLIENT_TRACE_MAX_LINES limits the number of lines of trace that are output + * to a file. Two files are used at most, when they are full, the last one is overwritten with the + * new trace entries. The default size is 1000 lines. + * + * #### Trace API calls + * + * MQTTAsync_traceCallback() is used to set a callback function which is called whenever trace + * information is available. This will be the same information as that printed if the + * environment variables were used to control the trace. + * + * The MQTTAsync_setTraceLevel() calls is used to set the maximum level of trace entries that will be + * passed to the callback function. The levels are: + * 1. ::MQTTASYNC_TRACE_MAXIMUM + * 2. ::MQTTASYNC_TRACE_MEDIUM + * 3. ::MQTTASYNC_TRACE_MINIMUM + * 4. ::MQTTASYNC_TRACE_PROTOCOL + * 5. ::MQTTASYNC_TRACE_ERROR + * 6. ::MQTTASYNC_TRACE_SEVERE + * 7. ::MQTTASYNC_TRACE_FATAL + * + * Selecting ::MQTTASYNC_TRACE_MAXIMUM will cause all trace entries at all levels to be returned. + * Choosing ::MQTTASYNC_TRACE_ERROR will cause ERROR, SEVERE and FATAL trace entries to be returned + * to the callback function. + * + * ### MQTT Packet Tracing + * + * A feature that can be very useful is printing the MQTT packets that are sent and received. To + * achieve this, use the following environment variable settings: + * @code + MQTT_C_CLIENT_TRACE=ON + MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL + * @endcode + * The output you should see looks like this: + * @code + 20130528 155936.813 3 stdout-subscriber -> CONNECT cleansession: 1 (0) + 20130528 155936.813 3 stdout-subscriber <- CONNACK rc: 0 + 20130528 155936.813 3 stdout-subscriber -> SUBSCRIBE msgid: 1 (0) + 20130528 155936.813 3 stdout-subscriber <- SUBACK msgid: 1 + 20130528 155941.818 3 stdout-subscriber -> DISCONNECT (0) + * @endcode + * where the fields are: + * 1. date + * 2. time + * 3. socket number + * 4. client id + * 5. direction (-> from client to server, <- from server to client) + * 6. packet details + * + * ### Default Level Tracing + * + * This is an extract of a default level trace of a call to connect: + * @code + 19700101 010000.000 (1152206656) (0)> MQTTClient_connect:893 + 19700101 010000.000 (1152206656) (1)> MQTTClient_connectURI:716 + 20130528 160447.479 Connecting to serverURI localhost:1883 + 20130528 160447.479 (1152206656) (2)> MQTTProtocol_connect:98 + 20130528 160447.479 (1152206656) (3)> MQTTProtocol_addressPort:48 + 20130528 160447.479 (1152206656) (3)< MQTTProtocol_addressPort:73 + 20130528 160447.479 (1152206656) (3)> Socket_new:599 + 20130528 160447.479 New socket 4 for localhost, port 1883 + 20130528 160447.479 (1152206656) (4)> Socket_addSocket:163 + 20130528 160447.479 (1152206656) (5)> Socket_setnonblocking:73 + 20130528 160447.479 (1152206656) (5)< Socket_setnonblocking:78 (0) + 20130528 160447.479 (1152206656) (4)< Socket_addSocket:176 (0) + 20130528 160447.479 (1152206656) (4)> Socket_error:95 + 20130528 160447.479 (1152206656) (4)< Socket_error:104 (115) + 20130528 160447.479 Connect pending + 20130528 160447.479 (1152206656) (3)< Socket_new:683 (115) + 20130528 160447.479 (1152206656) (2)< MQTTProtocol_connect:131 (115) + * @endcode + * where the fields are: + * 1. date + * 2. time + * 3. thread id + * 4. function nesting level + * 5. function entry (>) or exit (<) + * 6. function name : line of source code file + * 7. return value (if there is one) + * + * ### Memory Allocation Tracing + * + * Setting the trace level to maximum causes memory allocations and frees to be traced along with + * the default trace entries, with messages like the following: + * @code + 20130528 161819.657 Allocating 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 177 ptr 0x179f930 + + 20130528 161819.657 Freeing 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 201, heap use now 896 bytes + * @endcode + * When the last MQTT client object is destroyed, if the trace is being recorded + * and all memory allocated by the client library has not been freed, an error message will be + * written to the trace. This can help with fixing memory leaks. The message will look like this: + * @code + 20130528 163909.208 Some memory not freed at shutdown, possible memory leak + 20130528 163909.208 Heap scan start, total 880 bytes + 20130528 163909.208 Heap element size 32, line 354, file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c, ptr 0x260cb00 + 20130528 163909.208 Content + 20130528 163909.209 Heap scan end + * @endcode + * @endcond */ diff --git a/src/MQTTClient.c b/src/MQTTClient.c index 268af119..47a951a1 100644 --- a/src/MQTTClient.c +++ b/src/MQTTClient.c @@ -18,6 +18,12 @@ * Ian Craggs - multiple server connection support *******************************************************************************/ +/** + * @file + * \brief Synchronous API implementation + * + */ + #include #if !defined(WIN32) #include diff --git a/src/MQTTClient.h b/src/MQTTClient.h index 43be3fdc..ec352196 100644 --- a/src/MQTTClient.h +++ b/src/MQTTClient.h @@ -17,6 +17,25 @@ *******************************************************************************/ /** + * @cond MQTTClient_internal + * @mainpage MQTT Client Library Internals + * In the beginning there was one MQTT C client library, MQTTClient, as implemented in MQTTClient.c + * This library was designed to be easy to use for applications which didn't mind if some of the calls + * blocked for a while. For instance, the MQTTClient_connect call will block until a successful + * connection has completed, or a connection has failed, which could be as long as the "connection + * timeout" interval, whose default is 30 seconds. + * + * However in mobile devices and other windowing environments, blocking on the GUI thread is a bad + * thing as it causes the user interface to freeze. Hence a new API, MQTTAsync, implemented + * in MQTTAsync.c, was devised. There are no blocking calls in this library, so it is well suited + * to GUI and mobile environments, at the expense of some extra complexity. + * + * Both libraries are designed to be sparing in the use of threads. So multiple client objects are + * handled by one or two threads, with a select call in Socket_getReadySocket(), used to determine + * when a socket has incoming data. + * + * @endcond + * @cond MQTTClient_main * @mainpage MQTT Client library for C * © Copyright IBM Corp. 2009, 2013 * @@ -26,7 +45,7 @@ * considered easier to use. Some of the calls will block. For the new * totally asynchronous API where no calls block, which is especially suitable * for use in windowed environments, see the - * MQTT C Client Asynchronous API Documentation. + * MQTT C Client Asynchronous API Documentation. * * An MQTT client application connects to MQTT-capable servers. * A typical client is responsible for collecting information from a telemetry @@ -38,17 +57,16 @@ * API to the MQTT protocol using the programming language and platform of your * choice. This can be time-consuming and error-prone. * - * To simplify writing MQTT client applications, WebSphere MQ Telemetry provides - * C and Java client libraries that encapsulate the MQTT v3 protocol for a - * number of platforms. If you incorporate these libraries in your MQTT - * applications, a fully functional MQTT client can be written in a few lines of - * code. The information presented here documents the API provided by the IBM - * MQTT Client library for C. + * To simplify writing MQTT client applications, this library encapsulates + * the MQTT v3 protocol for you. Using this library enables a fully functional + * MQTT client application to be written in a few lines of code. + * The information presented here documents the API provided + * by the MQTT Client library for C. * * Using the client
* Applications that use the client library typically use a similar structure: *
    - *
  • Create a clent
  • + *
  • Create a client object
  • *
  • Set the options to connect to an MQTT server
  • *
  • Set up callback functions if multi-threaded (asynchronous mode) * operation is being used (see @ref async).
  • @@ -72,7 +90,9 @@ *
  • @ref async
  • *
  • @ref wildcard
  • *
  • @ref qos
  • + *
  • @ref tracing
  • *
+ * @endcond */ /// @cond EXCLUDE @@ -470,93 +490,98 @@ typedef struct { /** The eyecatcher for this structure. must be MQTC. */ char struct_id[4]; - /** The version number of this structure. Must be 0 or 1. 0 signifies no SSL options */ + /** The version number of this structure. Must be 0, 1 or 2. + * 0 signifies no SSL options and no serverURIs + * 1 signifies no serverURIs + */ int struct_version; /** The "keep alive" interval, measured in seconds, defines the maximum time - * that should pass without communication between the client and the server - * The client will ensure that at least one message travels across the - * network within each keep alive period. In the absence of a data-related - * message during the time period, the client sends a very small MQTT - * "ping" message, which the server will acknowledge. The keep alive - * interval enables the client to detect when the server is no longer - * available without having to wait for the long TCP/IP timeout. - */ + * that should pass without communication between the client and the server + * The client will ensure that at least one message travels across the + * network within each keep alive period. In the absence of a data-related + * message during the time period, the client sends a very small MQTT + * "ping" message, which the server will acknowledge. The keep alive + * interval enables the client to detect when the server is no longer + * available without having to wait for the long TCP/IP timeout. + */ int keepAliveInterval; /** - * This is a boolean value. The cleansession setting controls the behaviour - * of both the client and the server at connection and disconnection time. - * The client and server both maintain session state information. This - * information is used to ensure "at least once" and "exactly once" - * delivery, and "exactly once" receipt of messages. Session state also - * includes subscriptions created by an MQTT client. You can choose to - * maintain or discard state information between sessions. - * - * When cleansession is true, the state information is discarded at - * connect and disconnect. Setting cleansession to false keeps the state - * information. When you connect an MQTT client application with - * MQTTClient_connect(), the client identifies the connection using the - * client identifier and the address of the server. The server checks - * whether session information for this client - * has been saved from a previous connection to the server. If a previous - * session still exists, and cleansession=true, then the previous session - * information at the client and server is cleared. If cleansession=false, - * the previous session is resumed. If no previous session exists, a new - * session is started. - */ + * This is a boolean value. The cleansession setting controls the behaviour + * of both the client and the server at connection and disconnection time. + * The client and server both maintain session state information. This + * information is used to ensure "at least once" and "exactly once" + * delivery, and "exactly once" receipt of messages. Session state also + * includes subscriptions created by an MQTT client. You can choose to + * maintain or discard state information between sessions. + * + * When cleansession is true, the state information is discarded at + * connect and disconnect. Setting cleansession to false keeps the state + * information. When you connect an MQTT client application with + * MQTTClient_connect(), the client identifies the connection using the + * client identifier and the address of the server. The server checks + * whether session information for this client + * has been saved from a previous connection to the server. If a previous + * session still exists, and cleansession=true, then the previous session + * information at the client and server is cleared. If cleansession=false, + * the previous session is resumed. If no previous session exists, a new + * session is started. + */ int cleansession; /** - * This is a boolean value that controls how many messages can be in-flight - * simultaneously. Setting reliable to true means that a published - * message must be completed (acknowledgements received) before another - * can be sent. Attempts to publish additional messages receive an - * ::MQTTCLIENT_MAX_MESSAGES_INFLIGHT return code. Setting this flag to - * false allows up to 10 messages to be in-flight. This can increase - * overall throughput in some circumstances. - */ + * This is a boolean value that controls how many messages can be in-flight + * simultaneously. Setting reliable to true means that a published + * message must be completed (acknowledgements received) before another + * can be sent. Attempts to publish additional messages receive an + * ::MQTTCLIENT_MAX_MESSAGES_INFLIGHT return code. Setting this flag to + * false allows up to 10 messages to be in-flight. This can increase + * overall throughput in some circumstances. + */ int reliable; /** - * This is a pointer to an MQTTClient_willOptions structure. If your - * application does not make use of the Last Will and Testament feature, - * set this pointer to NULL. - */ + * This is a pointer to an MQTTClient_willOptions structure. If your + * application does not make use of the Last Will and Testament feature, + * set this pointer to NULL. + */ MQTTClient_willOptions* will; /** - * MQTT servers that support the MQTT v3.1 protocol provide authentication - * and authorisation by user name and password. This is the user name - * parameter. - */ + * MQTT servers that support the MQTT v3.1 protocol provide authentication + * and authorisation by user name and password. This is the user name + * parameter. + */ char* username; /** - * MQTT servers that support the MQTT v3.1 protocol provide authentication - * and authorisation by user name and password. This is the password - * parameter. - */ + * MQTT servers that support the MQTT v3.1 protocol provide authentication + * and authorisation by user name and password. This is the password + * parameter. + */ char* password; /** - * The time interval in seconds to allow a connect to complete. - */ + * The time interval in seconds to allow a connect to complete. + */ int connectTimeout; /** * The time interval in seconds */ int retryInterval; /** - * This is a pointer to an MQTTClient_SSLOptions structure. If your - * application does not make use of SSL, set this pointer to NULL. - */ + * This is a pointer to an MQTTClient_SSLOptions structure. If your + * application does not make use of SSL, set this pointer to NULL. + */ MQTTClient_SSLOptions* ssl; /** - * The number of entries in the serverURIs array. - */ + * The number of entries in the optional serverURIs array. Defaults to 0. + */ int serverURIcount; /** - * An array of null-terminated strings specifying the servers to - * which the client will connect. Each string takes the form protocol://host:port. - * protocol must be tcp or ssl. For host, you can - * specify either an IP address or a domain name. For instance, to connect to - * a server running on the local machines with the default MQTT port, specify - * tcp://localhost:1883. - */ + * An optional array of null-terminated strings specifying the servers to + * which the client will connect. Each string takes the form protocol://host:port. + * protocol must be tcp or ssl. For host, you can + * specify either an IP address or a host name. For instance, to connect to + * a server running on the local machines with the default MQTT port, specify + * tcp://localhost:1883. + * If this list is empty (the default), the server URI specified on MQTTClient_create() + * is used. + */ char** serverURIs; } MQTTClient_connectOptions; @@ -855,6 +880,7 @@ DLLExport void MQTTClient_destroy(MQTTClient* handle); #endif /** + * @cond MQTTClient_main * @page async Asynchronous vs synchronous client applications * The client library supports two modes of operation. These are referred to * as synchronous and asynchronous modes. If your application @@ -1174,4 +1200,94 @@ int main(int argc, char* argv[]) } * @endcode + * @page tracing Tracing + * + * Runtime tracing is controlled by environment variables. + * + * Tracing is switched on by setting MQTT_C_CLIENT_TRACE. A value of ON, or stdout, prints to + * stdout, any other value is interpreted as a file name to use. + * + * The amount of trace detail is controlled with the MQTT_C_CLIENT_TRACE_LEVEL environment + * variable - valid values are ERROR, PROTOCOL, MINIMUM, MEDIUM and MAXIMUM + * (from least to most verbose). + * + * The variable MQTT_C_CLIENT_TRACE_MAX_LINES limits the number of lines of trace that are output + * to a file. Two files are used at most, when they are full, the last one is overwritten with the + * new trace entries. The default size is 1000 lines. + * + * ### MQTT Packet Tracing + * + * A feature that can be very useful is printing the MQTT packets that are sent and received. To + * achieve this, use the following environment variable settings: + * @code + MQTT_C_CLIENT_TRACE=ON + MQTT_C_CLIENT_TRACE_LEVEL=PROTOCOL + * @endcode + * The output you should see looks like this: + * @code + 20130528 155936.813 3 stdout-subscriber -> CONNECT cleansession: 1 (0) + 20130528 155936.813 3 stdout-subscriber <- CONNACK rc: 0 + 20130528 155936.813 3 stdout-subscriber -> SUBSCRIBE msgid: 1 (0) + 20130528 155936.813 3 stdout-subscriber <- SUBACK msgid: 1 + 20130528 155941.818 3 stdout-subscriber -> DISCONNECT (0) + * @endcode + * where the fields are: + * 1. date + * 2. time + * 3. socket number + * 4. client id + * 5. direction (-> from client to server, <- from server to client) + * 6. packet details + * + * ### Default Level Tracing + * + * This is an extract of a default level trace of a call to connect: + * @code + 19700101 010000.000 (1152206656) (0)> MQTTClient_connect:893 + 19700101 010000.000 (1152206656) (1)> MQTTClient_connectURI:716 + 20130528 160447.479 Connecting to serverURI localhost:1883 + 20130528 160447.479 (1152206656) (2)> MQTTProtocol_connect:98 + 20130528 160447.479 (1152206656) (3)> MQTTProtocol_addressPort:48 + 20130528 160447.479 (1152206656) (3)< MQTTProtocol_addressPort:73 + 20130528 160447.479 (1152206656) (3)> Socket_new:599 + 20130528 160447.479 New socket 4 for localhost, port 1883 + 20130528 160447.479 (1152206656) (4)> Socket_addSocket:163 + 20130528 160447.479 (1152206656) (5)> Socket_setnonblocking:73 + 20130528 160447.479 (1152206656) (5)< Socket_setnonblocking:78 (0) + 20130528 160447.479 (1152206656) (4)< Socket_addSocket:176 (0) + 20130528 160447.479 (1152206656) (4)> Socket_error:95 + 20130528 160447.479 (1152206656) (4)< Socket_error:104 (115) + 20130528 160447.479 Connect pending + 20130528 160447.479 (1152206656) (3)< Socket_new:683 (115) + 20130528 160447.479 (1152206656) (2)< MQTTProtocol_connect:131 (115) + * @endcode + * where the fields are: + * 1. date + * 2. time + * 3. thread id + * 4. function nesting level + * 5. function entry (>) or exit (<) + * 6. function name : line of source code file + * 7. return value (if there is one) + * + * ### Memory Allocation Tracing + * + * Setting the trace level to maximum causes memory allocations and frees to be traced along with + * the default trace entries, with messages like the following: + * @code + 20130528 161819.657 Allocating 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 177 ptr 0x179f930 + + 20130528 161819.657 Freeing 16 bytes in heap at file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c line 201, heap use now 896 bytes + * @endcode + * When the last MQTT client object is destroyed, if the trace is being recorded + * and all memory allocated by the client library has not been freed, an error message will be + * written to the trace. This can help with fixing memory leaks. The message will look like this: + * @code + 20130528 163909.208 Some memory not freed at shutdown, possible memory leak + 20130528 163909.208 Heap scan start, total 880 bytes + 20130528 163909.208 Heap element size 32, line 354, file /home/icraggs/workspaces/mqrtc/mqttv3c/src/MQTTPacket.c, ptr 0x260cb00 + 20130528 163909.208 Content + 20130528 163909.209 Heap scan end + * @endcode + * @endcond */ diff --git a/src/utf-8.c b/src/utf-8.c index 75404fc1..e8d31192 100644 --- a/src/utf-8.c +++ b/src/utf-8.c @@ -15,32 +15,41 @@ *******************************************************************************/ -/* - See page 104 of the Unicode Standard 5.0 for the list of well formed - UTF-8 byte sequences. - -*/ +/** + * @file + * \brief Functions for checking that strings contain UTF-8 characters only + * + * See page 104 of the Unicode Standard 5.0 for the list of well formed + * UTF-8 byte sequences. + * + */ #include #include #include "StackTrace.h" +/** + * Macro to determine the number of elements in a single-dimension array + */ #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #endif +/** + * Structure to hold the valid ranges of UTF-8 characters, for each byte up to 4 + */ struct { - int len; + int len; /**< number of elements in the following array (1 to 4) */ struct { - char lower; - char upper; - } bytes[4]; + char lower; /**< lower limit of valid range */ + char upper; /**< upper limit of valid range */ + } bytes[4]; /**< up to 4 bytes can be used per character */ } -valid_ranges[] = +valid_ranges[] = { {1, { {00, 0x7F} } }, {2, { {0xC2, 0xDF}, {0x80, 0xBF} } }, @@ -54,6 +63,12 @@ valid_ranges[] = }; +/** + * Validate a single UTF-8 character + * @param len the length of the string in "data" + * @param data the bytes to check for a valid UTF-8 char + * @return pointer to the start of the next UTF-8 character in "data" + */ char* UTF8_char_validate(int len, char* data) { int good = 0; @@ -100,6 +115,12 @@ char* UTF8_char_validate(int len, char* data) } +/** + * Validate a length-delimited string has only UTF-8 characters + * @param len the length of the string in "data" + * @param data the bytes to check for valid UTF-8 characters + * @return 1 (true) if the string has only UTF-8 characters, 0 (false) otherwise + */ int UTF8_validate(int len, char* data) { char* curdata = NULL; @@ -116,6 +137,11 @@ int UTF8_validate(int len, char* data) } +/** + * Validate a null-terminated string has only UTF-8 characters + * @param string the string to check for valid UTF-8 characters + * @return 1 (true) if the string has only UTF-8 characters, 0 (false) otherwise + */ int UTF8_validateString(char* string) { int rc = 0;