diff --git a/config.json b/config.json index 28b174f..d201630 100644 --- a/config.json +++ b/config.json @@ -7,7 +7,6 @@ "info_topic": "/zxwl/sweeper/{vid}/info", "fault_topic": "/zxwl/sweeper/{vid}/fault", "gps_topic": "/zxwl/sweeper/{vid}/gps", - "pub_gps_topic": "/zxwl/sweeper/V060003/gps", "remote_topic": "/zxwl/sweeper/V060003/ctrl", "upload_url": "https://qsc.ntiov.com:8443/api/sys/route/upload", "download_url_pre": "http://36.153.162.171:9510/api/ccp-web/file/", diff --git a/src/communication/mqtt_report/include/mqtt_report/get_config.h b/src/communication/mqtt_report/include/mqtt_report/get_config.h index b0d4ee5..9ac98f7 100644 --- a/src/communication/mqtt_report/include/mqtt_report/get_config.h +++ b/src/communication/mqtt_report/include/mqtt_report/get_config.h @@ -24,9 +24,10 @@ struct Config std::string mqtt_username; std::string mqtt_password; - std::string info_topic_template; // e.g. /zxwl/vehicle/{vid}/info - std::string gps_topic_template; - std::string fault_topic_template; // e.g. /zxwl/vehicle/{vid}/fault + // ===== 上行 topic ===== + std::string info_topic_template; // /zxwl/sweeper/{vid}/info + std::string gps_topic_template; // /zxwl/sweeper/{vid}/gps + std::string fault_topic_template; // /zxwl/sweeper/{vid}/fault }; bool load_config(const std::string& path, Config& config); diff --git a/src/communication/mqtt_report/include/mqtt_report/mqtt_client.hpp b/src/communication/mqtt_report/include/mqtt_report/mqtt_client.hpp index c897a8a..06cf8fd 100644 --- a/src/communication/mqtt_report/include/mqtt_report/mqtt_client.hpp +++ b/src/communication/mqtt_report/include/mqtt_report/mqtt_client.hpp @@ -1,21 +1,23 @@ #pragma once -#include "paho_mqtt_3c/MQTTClient.h" -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include + +#include "paho_mqtt_3c/MQTTClient.h" class MQTTClientWrapper { -public: - MQTTClientWrapper(const std::string &server_uri, - const std::string &client_id, - const std::string &username = "", - const std::string &password = "", - int reconnect_interval_ms = 3000) + public: + using MessageHandler = std::function; + + MQTTClientWrapper(const std::string& server_uri, const std::string& client_id, const std::string& username = "", + const std::string& password = "", int reconnect_interval_ms = 3000) : server_uri_(server_uri), client_id_(client_id), username_(username), @@ -24,20 +26,17 @@ public: connected_(false), stop_flag_(false) { - int rc = MQTTClient_create(&client_, - server_uri_.c_str(), - client_id_.c_str(), - MQTTCLIENT_PERSISTENCE_NONE, - nullptr); + int rc = + MQTTClient_create(&client_, server_uri_.c_str(), client_id_.c_str(), MQTTCLIENT_PERSISTENCE_NONE, nullptr); if (rc != MQTTCLIENT_SUCCESS) { - std::cerr << "MQTTClient_create failed! rc=" << rc << std::endl; + std::cerr << "[MQTT] create failed rc=" << rc << std::endl; client_ = nullptr; return; } - MQTTClient_setCallbacks(client_, this, conn_lost_cb, nullptr, nullptr); + MQTTClient_setCallbacks(client_, this, conn_lost_cb, msg_arrived_cb, nullptr); reconnect_thread_ = std::thread([this]() { reconnectLoop(); }); } @@ -46,41 +45,36 @@ public: { stop_flag_ = true; - if (reconnect_thread_.joinable()) - reconnect_thread_.join(); + if (reconnect_thread_.joinable()) reconnect_thread_.join(); std::lock_guard lock(mtx_); if (client_) { - if (connected_) - MQTTClient_disconnect(client_, 2000); + if (connected_) MQTTClient_disconnect(client_, 2000); MQTTClient_destroy(&client_); } } - // 手动连接(可选) + // ===================== Connection ===================== + bool connect() { std::lock_guard lock(mtx_); return doConnect(); } - // 发布(非阻塞,无 waitForCompletion) - bool publish(const std::string &topic, - const std::string &payload, - int qos = 0, - bool retained = false) + bool isConnected() const { return connected_; } + + // ===================== Publish ===================== + + bool publish(const std::string& topic, const std::string& payload, int qos = 0, bool retained = false) { std::lock_guard lock(mtx_); - if (!client_) - return false; - - if (!connected_) - return false; + if (!client_ || !connected_) return false; MQTTClient_message msg = MQTTClient_message_initializer; - msg.payload = (void *)payload.c_str(); + msg.payload = (void*)payload.c_str(); msg.payloadlen = payload.size(); msg.qos = qos; msg.retained = retained ? 1 : 0; @@ -93,18 +87,54 @@ public: connected_ = false; return false; } - - // 非阻塞,不等待 completion return true; } - bool isConnected() const { return connected_; } + // ===================== Subscribe ===================== + + bool subscribe(const std::string& topic, int qos = 0) + { + std::lock_guard lock(mtx_); + if (!client_) return false; + + subscribed_topics_[topic] = qos; + + if (!connected_) return true; // 等重连后自动订阅 + + int rc = MQTTClient_subscribe(client_, topic.c_str(), qos); + if (rc != MQTTCLIENT_SUCCESS) + { + std::cerr << "[MQTT] subscribe failed rc=" << rc << std::endl; + return false; + } + return true; + } + + bool unsubscribe(const std::string& topic) + { + std::lock_guard lock(mtx_); + subscribed_topics_.erase(topic); + + if (!connected_ || !client_) return true; + + MQTTClient_unsubscribe(client_, topic.c_str()); + return true; + } + + // ===================== Message Handler ===================== + + void setMessageHandler(MessageHandler handler) + { + std::lock_guard lock(mtx_); + message_handler_ = std::move(handler); + } + + private: + // ===================== Internal ===================== -private: bool doConnect() { - if (!client_) - return false; + if (!client_) return false; MQTTClient_connectOptions opts = MQTTClient_connectOptions_initializer; opts.keepAliveInterval = 20; @@ -120,24 +150,45 @@ private: int rc = MQTTClient_connect(client_, &opts); if (rc == MQTTCLIENT_SUCCESS) { - std::cout << "[MQTT] Connected." << std::endl; connected_ = true; + std::cout << "[MQTT] Connected." << std::endl; + + // 重连后恢复订阅 + for (const auto& [topic, qos] : subscribed_topics_) + { + MQTTClient_subscribe(client_, topic.c_str(), qos); + } return true; } - std::cerr << "[MQTT] Connect failed rc=" << rc << std::endl; connected_ = false; return false; } - static void conn_lost_cb(void *context, char *cause) + static void conn_lost_cb(void* context, char* cause) { - auto *self = static_cast(context); + auto* self = static_cast(context); std::cerr << "[MQTT] Connection lost: " << (cause ? cause : "unknown") << std::endl; self->connected_ = false; } - // 自动重连线程 + static int msg_arrived_cb(void* context, char* topicName, int /*topicLen*/, MQTTClient_message* message) + { + auto* self = static_cast(context); + + std::string topic(topicName); + std::string payload(static_cast(message->payload), message->payloadlen); + + { + std::lock_guard lock(self->mtx_); + if (self->message_handler_) self->message_handler_(topic, payload); + } + + MQTTClient_freeMessage(&message); + MQTTClient_free(topicName); + return 1; + } + void reconnectLoop() { while (!stop_flag_) @@ -148,13 +199,13 @@ private: doConnect(); } - std::this_thread::sleep_for( - std::chrono::milliseconds(reconnect_interval_ms_)); + std::this_thread::sleep_for(std::chrono::milliseconds(reconnect_interval_ms_)); } } -private: - MQTTClient client_; + private: + MQTTClient client_{}; + std::string server_uri_; std::string client_id_; std::string username_; @@ -165,6 +216,9 @@ private: std::atomic connected_; std::atomic stop_flag_; + std::unordered_map subscribed_topics_; + MessageHandler message_handler_; + std::mutex mtx_; std::thread reconnect_thread_; }; diff --git a/src/communication/pub_gps/CMakeLists.txt b/src/communication/pub_gps/CMakeLists.txt deleted file mode 100644 index 7751d44..0000000 --- a/src/communication/pub_gps/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(pub_gps) - -# Default to C99 -if(NOT CMAKE_C_STANDARD) - set(CMAKE_C_STANDARD 99) -endif() - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - add_compile_options(-w) # 禁用所有警告 -endif() - -# find dependencies -find_package(ament_cmake REQUIRED) -find_package(rclcpp REQUIRED) -find_package(std_msgs REQUIRED) -find_package(sweeper_interfaces REQUIRED) - -include_directories( - include/pub_gps - include/paho_mqtt_3c -) - -add_executable(pub_gps_node - src/pub_gps_node.cpp - src/jsoncpp.cpp -) - -ament_target_dependencies(pub_gps_node rclcpp std_msgs sweeper_interfaces) - -if(CMAKE_SYSTEM_PROCESSOR MATCHES aarch64) - target_link_libraries( - pub_gps_node - ${PROJECT_SOURCE_DIR}/lib/libpaho-mqtt3c-static.a - ) -else() - target_link_libraries( - pub_gps_node - ${PROJECT_SOURCE_DIR}/lib/libpaho-mqtt3c.a - ) -endif() - -install(TARGETS - pub_gps_node - DESTINATION lib/${PROJECT_NAME} -) - -if(BUILD_TESTING) - find_package(ament_lint_auto REQUIRED) - # the following line skips the linter which checks for copyrights - # uncomment the line when a copyright and license is not present in all source files - #set(ament_cmake_copyright_FOUND TRUE) - # the following line skips cpplint (only works in a git repo) - # uncomment the line when this package is not in a git repo - #set(ament_cmake_cpplint_FOUND TRUE) - ament_lint_auto_find_test_dependencies() -endif() - -ament_package() diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Base64.h b/src/communication/pub_gps/include/paho_mqtt_3c/Base64.h deleted file mode 100644 index df9dd75..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Base64.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Keith Holman - initial implementation and documentation - *******************************************************************************/ - -#if !defined(BASE64_H) -#define BASE64_H - -/** type for size of a buffer, it saves passing around @p size_t (unsigned long long or unsigned long int) */ -typedef unsigned int b64_size_t; -/** type for raw base64 data */ -typedef unsigned char b64_data_t; - -/** - * Decodes base64 data - * - * @param[out] out decoded data - * @param[in] out_len length of output buffer - * @param[in] in base64 string to decode - * @param[in] in_len length of input buffer - * - * @return the amount of data decoded - * - * @see Base64_decodeLength - * @see Base64_encode - */ -b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, - const char *in, b64_size_t in_len ); - -/** - * Size of buffer required to decode base64 data - * - * @param[in] in base64 string to decode - * @param[in] in_len length of input buffer - * - * @return the size of buffer the decoded string would require - * - * @see Base64_decode - * @see Base64_encodeLength - */ -b64_size_t Base64_decodeLength( const char *in, b64_size_t in_len ); - -/** - * Encodes base64 data - * - * @param[out] out encode base64 string - * @param[in] out_len length of output buffer - * @param[in] in raw data to encode - * @param[in] in_len length of input buffer - * - * @return the amount of data encoded - * - * @see Base64_decode - * @see Base64_encodeLength - */ -b64_size_t Base64_encode( char *out, b64_size_t out_len, - const b64_data_t *in, b64_size_t in_len ); - -/** - * Size of buffer required to encode base64 data - * - * @param[in] in raw data to encode - * @param[in] in_len length of input buffer - * - * @return the size of buffer the encoded string would require - * - * @see Base64_decodeLength - * @see Base64_encode - */ -b64_size_t Base64_encodeLength( const b64_data_t *in, b64_size_t in_len ); - -#endif /* BASE64_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Clients.h b/src/communication/pub_gps/include/paho_mqtt_3c/Clients.h deleted file mode 100644 index fd32e3b..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Clients.h +++ /dev/null @@ -1,153 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - add SSL support - * Ian Craggs - fix for bug 413429 - connectionLost not called - * Ian Craggs - change will payload to binary - * Ian Craggs - password to binary - * Ian Craggs - MQTT 5 support - *******************************************************************************/ - -#if !defined(CLIENTS_H) -#define CLIENTS_H - -#include -#if defined(OPENSSL) -#if defined(WIN32) || defined(WIN64) -#include -#endif -#include -#endif -#include "MQTTClient.h" -#include "LinkedList.h" -#include "MQTTClientPersistence.h" - - -/** - * Stored publication data to minimize copying - */ -typedef struct -{ - char *topic; - int topiclen; - char* payload; - int payloadlen; - int refcount; -} Publications; - -/** - * Client publication message data - */ -typedef struct -{ - int qos; - int retain; - int msgid; - int MQTTVersion; - MQTTProperties properties; - Publications *publish; - time_t lastTouch; /**> used for retry and expiry */ - char nextMessageType; /**> PUBREC, PUBREL, PUBCOMP */ - int len; /**> length of the whole structure+data */ -} Messages; - -/** - * Client will message data - */ -typedef struct -{ - char *topic; - int payloadlen; - void *payload; - int retained; - int qos; -} willMessages; - -typedef struct -{ - int socket; - time_t lastSent; - time_t lastReceived; -#if defined(OPENSSL) - SSL* ssl; - SSL_CTX* ctx; -#endif - int websocket; /**< socket has been upgraded to use web sockets */ - char *websocket_key; -} networkHandles; - - -/* connection states */ -/** no connection in progress, see connected value */ -#define NOT_IN_PROGRESS 0x0 -/** TCP connection in progress */ -#define TCP_IN_PROGRESS 0x1 -/** SSL connection in progress */ -#define SSL_IN_PROGRESS 0x2 -/** Websocket connection in progress */ -#define WEBSOCKET_IN_PROGRESS 0x3 -/** TCP completed, waiting for MQTT ACK */ -#define WAIT_FOR_CONNACK 0x4 -/** Disconnecting */ -#define DISCONNECTING -2 - -/** - * Data related to one client - */ -typedef struct -{ - char* clientID; /**< the string id of the client */ - const char* username; /**< MQTT v3.1 user name */ - int passwordlen; /**< MQTT password length */ - const void* password; /**< MQTT v3.1 binary password */ - unsigned int cleansession : 1; /**< MQTT V3 clean session flag */ - unsigned int cleanstart : 1; /**< MQTT V5 clean start flag */ - unsigned int connected : 1; /**< whether it is currently connected */ - unsigned int good : 1; /**< if we have an error on the socket we turn this off */ - unsigned int ping_outstanding : 1; - signed int connect_state : 4; - networkHandles net; - int msgID; - int keepAliveInterval; - int retryInterval; - int maxInflightMessages; - willMessages* will; - List* inboundMsgs; - List* outboundMsgs; /**< in flight */ - List* messageQueue; - unsigned int qentry_seqno; - void* phandle; /* the persistence handle */ - MQTTClient_persistence* persistence; /* a persistence implementation */ - void* context; /* calling context - used when calling disconnect_internal */ - int MQTTVersion; - int sessionExpiry; /**< MQTT 5 session expiry */ -#if defined(OPENSSL) - MQTTClient_SSLOptions *sslopts; - SSL_SESSION* session; /***< SSL session pointer for fast handhake */ -#endif -} Clients; - -int clientIDCompare(void* a, void* b); -int clientSocketCompare(void* a, void* b); - -/** - * Configuration data related to all clients - */ -typedef struct -{ - const char* version; - List* clients; -} ClientStates; - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Heap.h b/src/communication/pub_gps/include/paho_mqtt_3c/Heap.h deleted file mode 100644 index 6d24c04..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Heap.h +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - use tree data structure instead of list - *******************************************************************************/ - - -#if !defined(HEAP_H) -#define HEAP_H - -#if defined(HIGH_PERFORMANCE) -#define NO_HEAP_TRACKING 1 -#endif - -#include -#include - -#if !defined(NO_HEAP_TRACKING) -/** - * redefines malloc to use "mymalloc" so that heap allocation can be tracked - * @param x the size of the item to be allocated - * @return the pointer to the item allocated, or NULL - */ -#define malloc(x) mymalloc(__FILE__, __LINE__, x) - -/** - * redefines realloc to use "myrealloc" so that heap allocation can be tracked - * @param a the heap item to be reallocated - * @param b the new size of the item - * @return the new pointer to the heap item - */ -#define realloc(a, b) myrealloc(__FILE__, __LINE__, a, b) - -/** - * redefines free to use "myfree" so that heap allocation can be tracked - * @param x the size of the item to be freed - */ -#define free(x) myfree(__FILE__, __LINE__, x) - -#endif - -/** - * Information about the state of the heap. - */ -typedef struct -{ - size_t current_size; /**< current size of the heap in bytes */ - size_t max_size; /**< max size the heap has reached in bytes */ -} heap_info; - -#if defined(__cplusplus) - extern "C" { -#endif - -void* mymalloc(char*, int, size_t size); -void* myrealloc(char*, int, void* p, size_t size); -void myfree(char*, int, void* p); - -void Heap_scan(FILE* file); -int Heap_initialize(void); -void Heap_terminate(void); -heap_info* Heap_get_info(void); -int HeapDump(FILE* file); -int HeapDumpString(FILE* file, char* str); -void* Heap_findItem(void* p); -void Heap_unlink(char* file, int line, void* p); -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/LinkedList.h b/src/communication/pub_gps/include/paho_mqtt_3c/LinkedList.h deleted file mode 100644 index 102a4fd..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/LinkedList.h +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - updates for the async client - * Ian Craggs - change size types from int to size_t - *******************************************************************************/ - -#if !defined(LINKEDLIST_H) -#define LINKEDLIST_H - -#include /* for size_t definition */ - -/*BE -defm defList(T) - -def T concat Item -{ - at 4 - n32 ptr T concat Item suppress "next" - at 0 - n32 ptr T concat Item suppress "prev" - at 8 - n32 ptr T id2str(T) -} - -def T concat List -{ - n32 ptr T concat Item suppress "first" - n32 ptr T concat Item suppress "last" - n32 ptr T concat Item suppress "current" - n32 dec "count" - n32 suppress "size" -} -endm - -defList(INT) -defList(STRING) -defList(TMP) - -BE*/ - -/** - * Structure to hold all data for one list element - */ -typedef struct ListElementStruct -{ - struct ListElementStruct *prev, /**< pointer to previous list element */ - *next; /**< pointer to next list element */ - void* content; /**< pointer to element content */ -} ListElement; - - -/** - * Structure to hold all data for one list - */ -typedef struct -{ - ListElement *first, /**< first element in the list */ - *last, /**< last element in the list */ - *current; /**< current element in the list, for iteration */ - int count; /**< no of items */ - size_t size; /**< heap storage used */ -} List; - -void ListZero(List*); -List* ListInitialize(void); - -void ListAppend(List* aList, void* content, size_t size); -void ListAppendNoMalloc(List* aList, void* content, ListElement* newel, size_t size); -void ListInsert(List* aList, void* content, size_t size, ListElement* index); - -int ListRemove(List* aList, void* content); -int ListRemoveItem(List* aList, void* content, int(*callback)(void*, void*)); -void* ListDetachHead(List* aList); -int ListRemoveHead(List* aList); -void* ListPopTail(List* aList); - -int ListDetach(List* aList, void* content); -int ListDetachItem(List* aList, void* content, int(*callback)(void*, void*)); - -void ListFree(List* aList); -void ListEmpty(List* aList); -void ListFreeNoContent(List* aList); - -ListElement* ListNextElement(List* aList, ListElement** pos); -ListElement* ListPrevElement(List* aList, ListElement** pos); - -ListElement* ListFind(List* aList, void* content); -ListElement* ListFindItem(List* aList, void* content, int(*callback)(void*, void*)); - -int intcompare(void* a, void* b); -int stringcompare(void* a, void* b); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Log.h b/src/communication/pub_gps/include/paho_mqtt_3c/Log.h deleted file mode 100644 index 455beb6..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Log.h +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - updates for the async client - *******************************************************************************/ - -#if !defined(LOG_H) -#define LOG_H - -/*BE -map LOG_LEVELS -{ - "TRACE_MAXIMUM" 1 - "TRACE_MEDIUM" 2 - "TRACE_MINIMUM" 3 - "TRACE_PROTOCOL" 4 - - "ERROR" 5 - "SEVERE" 6 - "FATAL" 7 -} -BE*/ - -enum LOG_LEVELS { - INVALID_LEVEL = -1, - TRACE_MAXIMUM = 1, - TRACE_MEDIUM, - TRACE_MINIMUM, - TRACE_PROTOCOL, - LOG_ERROR, - LOG_SEVERE, - LOG_FATAL, -}; - - -/*BE -def trace_settings_type -{ - n32 map LOG_LEVELS "trace_level" - n32 dec "max_trace_entries" - n32 dec "trace_output_level" -} -BE*/ -typedef struct -{ - enum LOG_LEVELS trace_level; /**< trace level */ - int max_trace_entries; /**< max no of entries in the trace buffer */ - enum LOG_LEVELS trace_output_level; /**< trace level to output to destination */ -} trace_settings_type; - -extern trace_settings_type trace_settings; - -#define LOG_PROTOCOL TRACE_PROTOCOL -#define TRACE_MAX TRACE_MAXIMUM -#define TRACE_MIN TRACE_MINIMUM -#define TRACE_MED TRACE_MEDIUM - -typedef struct -{ - const char* name; - const char* value; -} Log_nameValue; - -int Log_initialize(Log_nameValue*); -void Log_terminate(void); - -void Log(enum LOG_LEVELS, int, const char *, ...); -void Log_stackTrace(enum LOG_LEVELS, int, int, int, const char*, int, int*); - -typedef void Log_traceCallback(enum LOG_LEVELS level, const char *message); -void Log_setTraceCallback(Log_traceCallback* callback); -void Log_setTraceLevel(enum LOG_LEVELS level); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTAsync.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTAsync.h deleted file mode 100644 index 7b2067a..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTAsync.h +++ /dev/null @@ -1,2068 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation - * Ian Craggs, Allan Stockdill-Mander - SSL connections - * Ian Craggs - multiple server connection support - * Ian Craggs - MQTT 3.1.1 support - * Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked - * Ian Craggs - automatic reconnect and offline buffering (send while disconnected) - * Ian Craggs - binary will message - * Ian Craggs - binary password - * Ian Craggs - remove const on eyecatchers #168 - * Ian Craggs - MQTT 5.0 - *******************************************************************************/ - -/********************************************************************/ - -/** - * @cond MQTTAsync_main - * @mainpage Asynchronous MQTT client library for C - * - * © Copyright IBM Corp. 2009, 2018 - * - * @brief An Asynchronous MQTT client library for C. - * - * An MQTT client application connects to MQTT-capable servers. - * A typical client is responsible for collecting information from a telemetry - * device and publishing the information to the server. It can also subscribe - * to topics, receive messages, and use this information to control the - * telemetry device. - * - * MQTT clients implement the published MQTT v3 protocol. You can write your own - * 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, 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 client object
  • - *
  • Set the options to connect to an MQTT server
  • - *
  • Set up callback functions
  • - *
  • Connect the client to an MQTT server
  • - *
  • Subscribe to any topics the client needs to receive
  • - *
  • Repeat until finished:
  • - *
      - *
    • Publish any messages the client needs to
    • - *
    • Handle any incoming messages
    • - *
    - *
  • Disconnect the client
  • - *
  • Free any memory being used by the client
  • - *
- * Some simple examples are shown here: - *
    - *
  • @ref publish
  • - *
  • @ref subscribe
  • - *
- * Additional information about important concepts is provided here: - *
    - *
  • @ref async
  • - *
  • @ref wildcard
  • - *
  • @ref qos
  • - *
  • @ref tracing
  • - *
  • @ref auto_reconnect
  • - *
  • @ref offline_publish
  • - *
- * @endcond - */ - -/* -/// @cond EXCLUDE -*/ -#if !defined(MQTTASYNC_H) -#define MQTTASYNC_H - -#if defined(__cplusplus) - extern "C" { -#endif - -#if defined(WIN32) || defined(WIN64) - #define DLLImport __declspec(dllimport) - #define DLLExport __declspec(dllexport) -#else - #define DLLImport extern - #define DLLExport __attribute__ ((visibility ("default"))) -#endif - -#include -/* -/// @endcond -*/ - -#include "MQTTProperties.h" -#include "MQTTReasonCodes.h" -#include "MQTTSubscribeOpts.h" -#if !defined(NO_PERSISTENCE) -#include "MQTTClientPersistence.h" -#endif - -/** - * Return code: No error. Indicates successful completion of an MQTT client - * operation. - */ -#define MQTTASYNC_SUCCESS 0 -/** - * Return code: A generic error code indicating the failure of an MQTT client - * operation. - */ -#define MQTTASYNC_FAILURE -1 - -/* error code -2 is MQTTAsync_PERSISTENCE_ERROR */ - -#define MQTTASYNC_PERSISTENCE_ERROR -2 - -/** - * Return code: The client is disconnected. - */ -#define MQTTASYNC_DISCONNECTED -3 -/** - * Return code: The maximum number of messages allowed to be simultaneously - * in-flight has been reached. - */ -#define MQTTASYNC_MAX_MESSAGES_INFLIGHT -4 -/** - * Return code: An invalid UTF-8 string has been detected. - */ -#define MQTTASYNC_BAD_UTF8_STRING -5 -/** - * Return code: A NULL parameter has been supplied when this is invalid. - */ -#define MQTTASYNC_NULL_PARAMETER -6 -/** - * Return code: The topic has been truncated (the topic string includes - * embedded NULL characters). String functions will not access the full topic. - * Use the topic length value to access the full topic. - */ -#define MQTTASYNC_TOPICNAME_TRUNCATED -7 -/** - * Return code: A structure parameter does not have the correct eyecatcher - * and version number. - */ -#define MQTTASYNC_BAD_STRUCTURE -8 -/** - * Return code: A qos parameter is not 0, 1 or 2 - */ -#define MQTTASYNC_BAD_QOS -9 -/** - * Return code: All 65535 MQTT msgids are being used - */ -#define MQTTASYNC_NO_MORE_MSGIDS -10 -/** - * Return code: the request is being discarded when not complete - */ -#define MQTTASYNC_OPERATION_INCOMPLETE -11 -/** - * Return code: no more messages can be buffered - */ -#define MQTTASYNC_MAX_BUFFERED_MESSAGES -12 -/** - * Return code: Attempting SSL connection using non-SSL version of library - */ -#define MQTTASYNC_SSL_NOT_SUPPORTED -13 -/** - * Return code: protocol prefix in serverURI should be tcp:// or ssl:// - */ -#define MQTTASYNC_BAD_PROTOCOL -14 - /** - * Return code: don't use options for another version of MQTT - */ - #define MQTTASYNC_BAD_MQTT_OPTION -15 - /** - * Return code: call not applicable to the client's version of MQTT - */ - #define MQTTASYNC_WRONG_MQTT_VERSION -16 - - -/** - * Default MQTT version to connect with. Use 3.1.1 then fall back to 3.1 - */ -#define MQTTVERSION_DEFAULT 0 -/** - * MQTT version to connect with: 3.1 - */ -#define MQTTVERSION_3_1 3 -/** - * MQTT version to connect with: 3.1.1 - */ -#define MQTTVERSION_3_1_1 4 -/** - * MQTT version to connect with: 5 - */ -#define MQTTVERSION_5 5 -/** - * Bad return code from subscribe, as defined in the 3.1.1 specification - */ -#define MQTT_BAD_SUBSCRIBE 0x80 - - -/** - * Initialization options - */ -typedef struct -{ - /** The eyecatcher for this structure. Must be MQTG. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 */ - int struct_version; - /** 1 = we do openssl init, 0 = leave it to the application */ - int do_openssl_init; -} MQTTAsync_init_options; - -#define MQTTAsync_init_options_initializer { {'M', 'Q', 'T', 'G'}, 0, 0 } - -/** - * Global init of mqtt library. Call once on program start to set global behaviour. - * handle_openssl_init - if mqtt library should handle openssl init (1) or rely on the caller to init it before using mqtt (0) - */ -DLLExport void MQTTAsync_global_init(MQTTAsync_init_options* inits); - -/** - * A handle representing an MQTT client. A valid client handle is available - * following a successful call to MQTTAsync_create(). - */ -typedef void* MQTTAsync; -/** - * A value representing an MQTT message. A token is returned to the - * client application when a message is published. The token can then be used to - * check that the message was successfully delivered to its destination (see - * MQTTAsync_publish(), - * MQTTAsync_publishMessage(), - * MQTTAsync_deliveryComplete(), and - * MQTTAsync_getPendingTokens()). - */ -typedef int MQTTAsync_token; - -/** - * A structure representing the payload and attributes of an MQTT message. The - * message topic is not part of this structure (see MQTTAsync_publishMessage(), - * MQTTAsync_publish(), MQTTAsync_receive(), MQTTAsync_freeMessage() - * and MQTTAsync_messageArrived()). - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTM. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1. - * 0 indicates no message properties */ - int struct_version; - /** The length of the MQTT message payload in bytes. */ - int payloadlen; - /** A pointer to the payload of the MQTT message. */ - void* payload; - /** - * The quality of service (QoS) assigned to the message. - * There are three levels of QoS: - *
- *
QoS0
- *
Fire and forget - the message may not be delivered
- *
QoS1
- *
At least once - the message will be delivered, but may be - * delivered more than once in some circumstances.
- *
QoS2
- *
Once and one only - the message will be delivered exactly once.
- *
- */ - int qos; - /** - * The retained flag serves two purposes depending on whether the message - * it is associated with is being published or received. - * - * retained = true
- * For messages being published, a true setting indicates that the MQTT - * server should retain a copy of the message. The message will then be - * transmitted to new subscribers to a topic that matches the message topic. - * For subscribers registering a new subscription, the flag being true - * indicates that the received message is not a new one, but one that has - * been retained by the MQTT server. - * - * retained = false
- * For publishers, this indicates that this message should not be retained - * by the MQTT server. For subscribers, a false setting indicates this is - * a normal message, received as a result of it being published to the - * server. - */ - int retained; - /** - * The dup flag indicates whether or not this message is a duplicate. - * It is only meaningful when receiving QoS1 messages. When true, the - * client application should take appropriate action to deal with the - * duplicate message. - */ - int dup; - /** The message identifier is normally reserved for internal use by the - * MQTT client and server. - */ - int msgid; - /** - * The MQTT V5 properties associated with the message. - */ - MQTTProperties properties; -} MQTTAsync_message; - -#define MQTTAsync_message_initializer { {'M', 'Q', 'T', 'M'}, 1, 0, NULL, 0, 0, 0, 0, MQTTProperties_initializer } - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * receipt of messages. The function is registered with the client library by - * passing it as an argument to MQTTAsync_setCallbacks(). It is - * called by the client library when a new message that matches a client - * subscription has been received from the server. This function is executed on - * a separate thread to the one on which the client application is running. - * @param context A pointer to the context value originally passed to - * MQTTAsync_setCallbacks(), which contains any application-specific context. - * @param topicName The topic associated with the received message. - * @param topicLen The length of the topic if there are one - * more NULL characters embedded in topicName, otherwise topicLen - * is 0. If topicLen is 0, the value returned by strlen(topicName) - * can be trusted. If topicLen is greater than 0, the full topic name - * can be retrieved by accessing topicName as a byte array of length - * topicLen. - * @param message The MQTTAsync_message structure for the received message. - * This structure contains the message payload and attributes. - * @return This function must return a boolean value indicating whether or not - * the message has been safely received by the client application. Returning - * true indicates that the message has been successfully handled. - * Returning false indicates that there was a problem. In this - * case, the client library will reinvoke MQTTAsync_messageArrived() to - * attempt to deliver the message to the application again. - */ -typedef int MQTTAsync_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message); - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of delivery of messages to the server. The function is - * registered with the client library by passing it as an argument to MQTTAsync_setCallbacks(). - * It is called by the client library after the client application has - * published a message to the server. It indicates that the necessary - * handshaking and acknowledgements for the requested quality of service (see - * MQTTAsync_message.qos) have been completed. This function is executed on a - * separate thread to the one on which the client application is running. - * @param context A pointer to the context value originally passed to - * MQTTAsync_setCallbacks(), which contains any application-specific context. - * @param token The ::MQTTAsync_token associated with - * the published message. Applications can check that all messages have been - * correctly published by matching the tokens returned from calls to - * MQTTAsync_send() and MQTTAsync_sendMessage() with the tokens passed - * to this callback. - */ -typedef void MQTTAsync_deliveryComplete(void* context, MQTTAsync_token token); - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of the loss of connection to the server. The function is - * registered with the client library by passing it as an argument to - * MQTTAsync_setCallbacks(). It is called by the client library if the client - * loses its connection to the server. The client application must take - * appropriate action, such as trying to reconnect or reporting the problem. - * This function is executed on a separate thread to the one on which the - * client application is running. - * @param context A pointer to the context value originally passed to - * MQTTAsync_setCallbacks(), which contains any application-specific context. - * @param cause The reason for the disconnection. - * Currently, cause is always set to NULL. - */ -typedef void MQTTAsync_connectionLost(void* context, char* cause); - - -/** - * This is a callback function, which will be called when the client - * library successfully connects. This is superfluous when the connection - * is made in response to a MQTTAsync_connect call, because the onSuccess - * callback can be used. It is intended for use when automatic reconnect - * is enabled, so that when a reconnection attempt succeeds in the background, - * the application is notified and can take any required actions. - * @param context A pointer to the context value originally passed to - * MQTTAsync_setCallbacks(), which contains any application-specific context. - * @param cause The reason for the disconnection. - * Currently, cause is always set to NULL. - */ -typedef void MQTTAsync_connected(void* context, char* cause); - -/** - * This is a callback function, which will be called when the client - * library receives a disconnect packet. - * @param context A pointer to the context value originally passed to - * MQTTAsync_setCallbacks(), which contains any application-specific context. - * @param properties the properties in the disconnect packet. - * @param properties the reason code from the disconnect packet - * Currently, cause is always set to NULL. - */ -typedef void MQTTAsync_disconnected(void* context, MQTTProperties* properties, - enum MQTTReasonCodes reasonCode); - -/** - * Sets the MQTTAsync_disconnected() callback function for a client. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to each of the callback functions to - * provide access to the context information in the callback. - * @param co A pointer to an MQTTAsync_connected() callback - * function. NULL removes the callback setting. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_setDisconnected(MQTTAsync handle, void* context, MQTTAsync_disconnected* co); - - -/** The data returned on completion of an unsuccessful API call in the response callback onFailure. */ -typedef struct -{ - /** A token identifying the failed request. */ - MQTTAsync_token token; - /** A numeric code identifying the error. */ - int code; - /** Optional text explaining the error. Can be NULL. */ - const char *message; -} MQTTAsync_failureData; - - -/** The data returned on completion of an unsuccessful API call in the response callback onFailure. */ -typedef struct -{ - /** The eyecatcher for this structure. Will be MQFD. */ - char struct_id[4]; - /** The version number of this structure. Will be 0 */ - int struct_version; - /** A token identifying the failed request. */ - MQTTAsync_token token; - /** The MQTT reason code returned. */ - enum MQTTReasonCodes reasonCode; - /** The MQTT properties on the ack, if any. */ - MQTTProperties properties; - /** A numeric code identifying the MQTT client library error. */ - int code; - /** Optional further text explaining the error. Can be NULL. */ - const char *message; - /** Packet type on which the failure occurred - used for publish QoS 1/2 exchanges*/ - int packet_type; -} MQTTAsync_failureData5; - -#define MQTTAsync_failureData5_initializer {{'M', 'Q', 'F', 'D'}, 0, 0, MQTTREASONCODE_SUCCESS, MQTTProperties_initializer, 0, NULL} - -/** The data returned on completion of a successful API call in the response callback onSuccess. */ -typedef struct -{ - /** A token identifying the successful request. Can be used to refer to the request later. */ - MQTTAsync_token token; - /** A union of the different values that can be returned for subscribe, unsubscribe and publish. */ - union - { - /** For subscribe, the granted QoS of the subscription returned by the server. */ - int qos; - /** For subscribeMany, the list of granted QoSs of the subscriptions returned by the server. */ - int* qosList; - /** For publish, the message being sent to the server. */ - struct - { - MQTTAsync_message message; - char* destinationName; - } pub; - /* For connect, the server connected to, MQTT version used, and sessionPresent flag */ - struct - { - char* serverURI; - int MQTTVersion; - int sessionPresent; - } connect; - } alt; -} MQTTAsync_successData; - - -/** The data returned on completion of a successful API call in the response callback onSuccess. */ -typedef struct -{ - char struct_id[4]; /**< The eyecatcher for this structure. Will be MQSD. */ - int struct_version; /**< The version number of this structure. Will be 0 */ - /** A token identifying the successful request. Can be used to refer to the request later. */ - MQTTAsync_token token; - enum MQTTReasonCodes reasonCode; /**< MQTT V5 reason code returned */ - MQTTProperties properties; /**< MQTT V5 properties returned, if any */ - /** A union of the different values that can be returned for subscribe, unsubscribe and publish. */ - union - { - /** For subscribeMany, the list of reasonCodes returned by the server. */ - struct - { - int reasonCodeCount; /**< the number of reason codes in the reasonCodes array */ - enum MQTTReasonCodes* reasonCodes; /**< an array of reasonCodes */ - } sub; - /** For publish, the message being sent to the server. */ - struct - { - MQTTAsync_message message; /**< the message being sent to the server */ - char* destinationName; /**< the topic destination for the message */ - } pub; - /* For connect, the server connected to, MQTT version used, and sessionPresent flag */ - struct - { - char* serverURI; /**< the connection string of the server */ - int MQTTVersion; /**< the version of MQTT being used */ - int sessionPresent; /**< the session present flag returned from the server */ - } connect; - /** For unsubscribeMany, the list of reasonCodes returned by the server. */ - struct - { - int reasonCodeCount; /**< the number of reason codes in the reasonCodes array */ - enum MQTTReasonCodes* reasonCodes; /**< an array of reasonCodes */ - } unsub; - } alt; -} MQTTAsync_successData5; - -#define MQTTAsync_successData5_initializer {{'M', 'Q', 'S', 'D'}, 0, 0, MQTTREASONCODE_SUCCESS, MQTTProperties_initializer} - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of the successful completion of an API call. The function is - * registered with the client library by passing it as an argument in - * ::MQTTAsync_responseOptions. - * @param context A pointer to the context value originally passed to - * ::MQTTAsync_responseOptions, which contains any application-specific context. - * @param response Any success data associated with the API completion. - */ -typedef void MQTTAsync_onSuccess(void* context, MQTTAsync_successData* response); - -/** - * This is a callback function, the MQTT V5 version of ::MQTTAsync_onSuccess. - * The client application - * must provide an implementation of this function to enable asynchronous - * notification of the successful completion of an API call. The function is - * registered with the client library by passing it as an argument in - * ::MQTTAsync_responseOptions. - * @param context A pointer to the context value originally passed to - * ::MQTTAsync_responseOptions, which contains any application-specific context. - * @param response Any success data associated with the API completion. - */ -typedef void MQTTAsync_onSuccess5(void* context, MQTTAsync_successData5* response); - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of the unsuccessful completion of an API call. The function is - * registered with the client library by passing it as an argument in - * ::MQTTAsync_responseOptions. - * @param context A pointer to the context value originally passed to - * ::MQTTAsync_responseOptions, which contains any application-specific context. - * @param response Failure data associated with the API completion. - */ -typedef void MQTTAsync_onFailure(void* context, MQTTAsync_failureData* response); - -/** - * This is a callback function, the MQTT V5 version of ::MQTTAsync_onFailure. - * The application must provide an implementation of this function to enable asynchronous - * notification of the unsuccessful completion of an API call. The function is - * registered with the client library by passing it as an argument in - * ::MQTTAsync_responseOptions. - * @param context A pointer to the context value originally passed to - * ::MQTTAsync_responseOptions, which contains any application-specific context. - * @param response Failure data associated with the API completion. - */ -typedef void MQTTAsync_onFailure5(void* context, MQTTAsync_failureData5* response); - -typedef struct MQTTAsync_responseOptions -{ - /** The eyecatcher for this structure. Must be MQTR */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 - * if 0, no MQTTV5 options */ - int struct_version; - /** - * A pointer to a callback function to be called if the API call successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess* onSuccess; - /** - * A pointer to a callback function to be called if the API call fails. - * Can be set to NULL, in which case no indication of unsuccessful - * completion will be received. - */ - MQTTAsync_onFailure* onFailure; - /** - * A pointer to any application-specific context. The - * the context pointer is passed to success or failure callback functions to - * provide access to the context information in the callback. - */ - void* context; - /** - * A token is returned from the call. It can be used to track - * the state of this request, both in the callbacks and in future calls - * such as ::MQTTAsync_waitForCompletion. - */ - MQTTAsync_token token; - /** - * A pointer to a callback function to be called if the API call successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess5* onSuccess5; - /** - * A pointer to a callback function to be called if the API call successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onFailure5* onFailure5; - /** - * MQTT V5 input properties - */ - MQTTProperties properties; - /* - * MQTT V5 subscribe options, when used with subscribe only. - */ - MQTTSubscribe_options subscribeOptions; - /* - * MQTT V5 subscribe option count, when used with subscribeMany only. - * The number of entries in the subscribe_options_list array. - */ - int subscribeOptionsCount; - /* - * MQTT V5 subscribe option array, when used with subscribeMany only. - */ - MQTTSubscribe_options* subscribeOptionsList; -} MQTTAsync_responseOptions; - -#define MQTTAsync_responseOptions_initializer { {'M', 'Q', 'T', 'R'}, 1, NULL, NULL, 0, 0, NULL, NULL, MQTTProperties_initializer, MQTTSubscribe_options_initializer, 0, NULL} - -typedef struct MQTTAsync_responseOptions MQTTAsync_callOptions; -#define MQTTAsync_callOptions_initializer MQTTAsync_responseOptions_initializer - -/** - * This function sets the global callback functions for a specific client. - * If your client application doesn't use a particular callback, set the - * relevant parameter to NULL. Any necessary message acknowledgements and - * status communications are handled in the background without any intervention - * from the client application. If you do not set a messageArrived callback - * function, you will not be notified of the receipt of any messages as a - * result of a subscription. - * - * Note: The MQTT client must be disconnected when this function is - * called. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to each of the callback functions to - * provide access to the context information in the callback. - * @param cl A pointer to an MQTTAsync_connectionLost() callback - * function. You can set this to NULL if your application doesn't handle - * disconnections. - * @param ma A pointer to an MQTTAsync_messageArrived() callback - * function. You can set this to NULL if your application doesn't handle - * receipt of messages. - * @param dc A pointer to an MQTTAsync_deliveryComplete() callback - * function. You can set this to NULL if you do not want to check - * for successful delivery. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_setCallbacks(MQTTAsync handle, void* context, MQTTAsync_connectionLost* cl, - MQTTAsync_messageArrived* ma, MQTTAsync_deliveryComplete* dc); - -/** - * This function sets the callback function for a connection lost event for - * a specific client. Any necessary message acknowledgements and status - * communications are handled in the background without any intervention - * from the client application. - * - * Note: The MQTT client must be disconnected when this function is - * called. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed the callback functions to provide - * access to the context information in the callback. - * @param cl A pointer to an MQTTAsync_connectionLost() callback - * function. You can set this to NULL if your application doesn't handle - * disconnections. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ - -DLLExport int MQTTAsync_setConnectionLostCallback(MQTTAsync handle, void* context, - MQTTAsync_connectionLost* cl); - -/** - * This function sets the callback function for a message arrived event for - * a specific client. Any necessary message acknowledgements and status - * communications are handled in the background without any intervention - * from the client application. If you do not set a messageArrived callback - * function, you will not be notified of the receipt of any messages as a - * result of a subscription. - * - * Note: The MQTT client must be disconnected when this function is - * called. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to the callback functions to provide - * access to the context information in the callback. - * @param ma A pointer to an MQTTAsync_messageArrived() callback - * function. You can set this to NULL if your application doesn't handle - * receipt of messages. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_setMessageArrivedCallback(MQTTAsync handle, void* context, - MQTTAsync_messageArrived* ma); - -/** - * This function sets the callback function for a delivery complete event - * for a specific client. Any necessary message acknowledgements and status - * communications are handled in the background without any intervention - * from the client application. - * - * Note: The MQTT client must be disconnected when this function is - * called. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to the callback functions to provide - * access to the context information in the callback. - * @param dc A pointer to an MQTTAsync_deliveryComplete() callback - * function. You can set this to NULL if you do not want to check - * for successful delivery. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_setDeliveryCompleteCallback(MQTTAsync handle, void* context, - MQTTAsync_deliveryComplete* dc); - -/** - * Sets the MQTTAsync_connected() callback function for a client. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to each of the callback functions to - * provide access to the context information in the callback. - * @param co A pointer to an MQTTAsync_connected() callback - * function. NULL removes the callback setting. - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_setConnected(MQTTAsync handle, void* context, MQTTAsync_connected* co); - - -/** - * Reconnects a client with the previously used connect options. Connect - * must have previously been called for this to work. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @return ::MQTTASYNC_SUCCESS if the callbacks were correctly set, - * ::MQTTASYNC_FAILURE if an error occurred. - */ -DLLExport int MQTTAsync_reconnect(MQTTAsync handle); - - -/** - * This function creates an MQTT client ready for connection to the - * specified server and using the specified persistent storage (see - * MQTTAsync_persistence). See also MQTTAsync_destroy(). - * @param handle A pointer to an ::MQTTAsync handle. The handle is - * populated with a valid client reference following a successful return from - * this function. - * @param serverURI A null-terminated string specifying the server to - * which the client will connect. It 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. - * @param clientId The client identifier passed to the server when the - * client connects to it. It is a null-terminated UTF-8 encoded string. - * @param persistence_type The type of persistence to be used by the client: - *
- * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or - * system on which the client is running fails or is switched off, the current - * state of any in-flight messages is lost and some messages may not be - * delivered even at QoS1 and QoS2. - *
- * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based) - * persistence mechanism. Status about in-flight messages is held in persistent - * storage and provides some protection against message loss in the case of - * unexpected failure. - *
- * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence - * implementation. Using this type of persistence gives control of the - * persistence mechanism to the application. The application has to implement - * the MQTTClient_persistence interface. - * @param persistence_context If the application uses - * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should - * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it - * should be set to the location of the persistence directory (if set - * to NULL, the persistence directory used is the working directory). - * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this - * argument to point to a valid MQTTClient_persistence structure. - * @return ::MQTTASYNC_SUCCESS if the client is successfully created, otherwise - * an error code is returned. - */ -DLLExport int MQTTAsync_create(MQTTAsync* handle, const char* serverURI, const char* clientId, - int persistence_type, void* persistence_context); - -typedef struct -{ - /** The eyecatcher for this structure. must be MQCO. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 - * 0 means no MQTTVersion - */ - int struct_version; - /** Whether to allow messages to be sent when the client library is not connected. */ - int sendWhileDisconnected; - /** the maximum number of messages allowed to be buffered while not connected. */ - int maxBufferedMessages; - /** Whether the MQTT version is 3.1, 3.1.1, or 5. To use V5, this must be set. - * MQTT V5 has to be chosen here, because during the create call the message persistence - * is initialized, and we want to know whether the format of any persisted messages - * is appropriate for the MQTT version we are going to connect with. Selecting 3.1 or - * 3.1.1 and attempting to read 5.0 persisted messages will result in an error on create. */ - int MQTTVersion; -} MQTTAsync_createOptions; - -#define MQTTAsync_createOptions_initializer { {'M', 'Q', 'C', 'O'}, 0, 0, 100, MQTTVERSION_DEFAULT } - - -DLLExport int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId, - int persistence_type, void* persistence_context, MQTTAsync_createOptions* options); - -/** - * MQTTAsync_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for - * the client. In the event that a client unexpectedly loses its connection to - * the server, the server publishes the LWT message to the LWT topic on - * behalf of the client. This allows other clients (subscribed to the LWT topic) - * to be made aware that the client has disconnected. To enable the LWT - * function for a specific client, a valid pointer to an MQTTAsync_willOptions - * structure is passed in the MQTTAsync_connectOptions structure used in the - * MQTTAsync_connect() call that connects the client to the server. The pointer - * to MQTTAsync_willOptions can be set to NULL if the LWT function is not - * required. - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTW. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 - 0 indicates no binary will message support - */ - int struct_version; - /** The LWT topic to which the LWT message will be published. */ - const char* topicName; - /** The LWT payload. */ - const char* message; - /** - * The retained flag for the LWT message (see MQTTAsync_message.retained). - */ - int retained; - /** - * The quality of service setting for the LWT message (see - * MQTTAsync_message.qos and @ref qos). - */ - int qos; - /** The LWT payload in binary form. This is only checked and used if the message option is NULL */ - struct - { - int len; /**< binary payload length */ - const void* data; /**< binary payload data */ - } payload; -} MQTTAsync_willOptions; - -#define MQTTAsync_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, { 0, NULL } } - -#define MQTT_SSL_VERSION_DEFAULT 0 -#define MQTT_SSL_VERSION_TLS_1_0 1 -#define MQTT_SSL_VERSION_TLS_1_1 2 -#define MQTT_SSL_VERSION_TLS_1_2 3 - -/** -* MQTTAsync_sslProperties defines the settings to establish an SSL/TLS connection using the -* OpenSSL library. It covers the following scenarios: -* - Server authentication: The client needs the digital certificate of the server. It is included -* in a store containting trusted material (also known as "trust store"). -* - Mutual authentication: Both client and server are authenticated during the SSL handshake. In -* addition to the digital certificate of the server in a trust store, the client will need its own -* digital certificate and the private key used to sign its digital certificate stored in a "key store". -* - Anonymous connection: Both client and server do not get authenticated and no credentials are needed -* to establish an SSL connection. Note that this scenario is not fully secure since it is subject to -* man-in-the-middle attacks. -*/ -typedef struct -{ - /** The eyecatcher for this structure. Must be MQTS */ - char struct_id[4]; - /** The version number of this structure. Must be 0, or 1 to enable TLS version selection. */ - int struct_version; - - /** The file in PEM format containing the public digital certificates trusted by the client. */ - const char* trustStore; - - /** The file in PEM format containing the public certificate chain of the client. It may also include - * the client's private key. - */ - const char* keyStore; - - /** If not included in the sslKeyStore, this setting points to the file in PEM format containing - * the client's private key. - */ - const char* privateKey; - /** The password to load the client's privateKey if encrypted. */ - const char* privateKeyPassword; - - /** - * The list of cipher suites that the client will present to the server during the SSL handshake. For a - * full explanation of the cipher list format, please see the OpenSSL on-line documentation: - * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT - * If this setting is ommitted, its default value will be "ALL", that is, all the cipher suites -excluding - * those offering no encryption- will be considered. - * This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance). - */ - const char* enabledCipherSuites; - - /** True/False option to enable verification of the server certificate **/ - int enableServerCertAuth; - - /** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0), - * MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3). - * Only used if struct_version is >= 1. - */ - int sslVersion; - - /** - * Whether to carry out post-connect checks, including that a certificate - * matches the given host name. - * Exists only if struct_version >= 2 - */ - int verify; - - /** - * From the OpenSSL documentation: - * If CApath is not NULL, it points to a directory containing CA certificates in PEM format. - * Exists only if struct_version >= 2 - */ - const char* CApath; - - /** - * Callback function for OpenSSL error handler ERR_print_errors_cb - * Exists only if struct_version >= 3 - */ - int (*ssl_error_cb) (const char *str, size_t len, void *u); - - /** - * Application-specific contex for OpenSSL error handler ERR_print_errors_cb - * Exists only if struct_version >= 3 - */ - void* ssl_error_context; -} MQTTAsync_SSLOptions; - -#define MQTTAsync_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 3, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL } - -/** - * MQTTAsync_connectOptions defines several settings that control the way the - * client connects to an MQTT server. Default values are set in - * MQTTAsync_connectOptions_initializer. - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTC. */ - char struct_id[4]; - /** The version number of this structure. Must be 0, 1, 2, 3 4 5 or 6. - * 0 signifies no SSL options and no serverURIs - * 1 signifies no serverURIs - * 2 signifies no MQTTVersion - * 3 signifies no automatic reconnect options - * 4 signifies no binary password option (just string) - * 5 signifies no MQTTV5 properties - */ - 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. - * Set to 0 if you do not want any keep alive processing. - */ - 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 - * MQTTAsync_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 controls how many messages can be in-flight simultaneously. - */ - int maxInflight; - /** - * This is a pointer to an MQTTAsync_willOptions structure. If your - * application does not make use of the Last Will and Testament feature, - * set this pointer to NULL. - */ - MQTTAsync_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. - */ - const 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. - */ - const char* password; - /** - * The time interval in seconds to allow a connect to complete. - */ - int connectTimeout; - /** - * The time interval in seconds after which unacknowledged publish requests are - * retried during a TCP session. With MQTT 3.1.1 and later, retries are - * not required except on reconnect. 0 turns off in-session retries, and is the - * recommended setting. Adding retries to an already overloaded network only - * exacerbates the problem. - */ - int retryInterval; - /** - * This is a pointer to an MQTTAsync_SSLOptions structure. If your - * application does not make use of SSL, set this pointer to NULL. - */ - MQTTAsync_SSLOptions* ssl; - /** - * A pointer to a callback function to be called if the connect successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess* onSuccess; - /** - * A pointer to a callback function to be called if the connect fails. - * Can be set to NULL, in which case no indication of unsuccessful - * completion will be received. - */ - MQTTAsync_onFailure* onFailure; - /** - * A pointer to any application-specific context. The - * the context pointer is passed to success or failure callback functions to - * provide access to the context information in the callback. - */ - void* context; - /** - * The number of entries in the serverURIs array. - */ - 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. - */ - char* const* serverURIs; - /** - * Sets the version of MQTT to be used on the connect. - * MQTTVERSION_DEFAULT (0) = default: start with 3.1.1, and if that fails, fall back to 3.1 - * MQTTVERSION_3_1 (3) = only try version 3.1 - * MQTTVERSION_3_1_1 (4) = only try version 3.1.1 - */ - int MQTTVersion; - /** - * Reconnect automatically in the case of a connection being lost? - */ - int automaticReconnect; - /** - * Minimum retry interval in seconds. Doubled on each failed retry. - */ - int minRetryInterval; - /** - * Maximum retry interval in seconds. The doubling stops here on failed retries. - */ - int maxRetryInterval; - /** - * Optional binary password. Only checked and used if the password option is NULL - */ - struct { - int len; /**< binary password length */ - const void* data; /**< binary password data */ - } binarypwd; - /* - * MQTT V5 clean start flag. Only clears state at the beginning of the session. - */ - int cleanstart; - /** - * MQTT V5 properties for connect - */ - MQTTProperties *connectProperties; - /** - * MQTT V5 properties for the will message in the connect - */ - MQTTProperties *willProperties; - /** - * A pointer to a callback function to be called if the connect successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess5* onSuccess5; - /** - * A pointer to a callback function to be called if the connect fails. - * Can be set to NULL, in which case no indication of unsuccessful - * completion will be received. - */ - MQTTAsync_onFailure5* onFailure5; -} MQTTAsync_connectOptions; - - -#define MQTTAsync_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 6, 60, 1, 65535, NULL, NULL, NULL, 30, 0,\ -NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_DEFAULT, 0, 1, 60, {0, NULL}, 0, NULL, NULL, NULL, NULL} - -#define MQTTAsync_connectOptions_initializer5 { {'M', 'Q', 'T', 'C'}, 6, 60, 0, 65535, NULL, NULL, NULL, 30, 0,\ -NULL, NULL, NULL, NULL, 0, NULL, MQTTVERSION_5, 0, 1, 60, {0, NULL}, 1, NULL, NULL, NULL, NULL} - - -/** - * This function attempts to connect a previously-created client (see - * MQTTAsync_create()) to an MQTT server using the specified options. If you - * want to enable asynchronous message and status notifications, you must call - * MQTTAsync_setCallbacks() prior to MQTTAsync_connect(). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param options A pointer to a valid MQTTAsync_connectOptions - * structure. - * @return ::MQTTASYNC_SUCCESS if the client connect request was accepted. - * If the client was unable to connect to the server, an error code is - * returned via the onFailure callback, if set. - * Error codes greater than 0 are returned by the MQTT protocol:

- * 1: Connection refused: Unacceptable protocol version
- * 2: Connection refused: Identifier rejected
- * 3: Connection refused: Server unavailable
- * 4: Connection refused: Bad user name or password
- * 5: Connection refused: Not authorized
- * 6-255: Reserved for future use
- */ -DLLExport int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options); - - -typedef struct -{ - /** The eyecatcher for this structure. Must be MQTD. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1. 0 signifies no V5 properties */ - int struct_version; - /** - * The client delays disconnection for up to this time (in - * milliseconds) in order to allow in-flight message transfers to complete. - */ - int timeout; - /** - * A pointer to a callback function to be called if the disconnect successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess* onSuccess; - /** - * A pointer to a callback function to be called if the disconnect fails. - * Can be set to NULL, in which case no indication of unsuccessful - * completion will be received. - */ - MQTTAsync_onFailure* onFailure; - /** - * A pointer to any application-specific context. The - * the context pointer is passed to success or failure callback functions to - * provide access to the context information in the callback. - */ - void* context; - /** - * MQTT V5 input properties - */ - MQTTProperties properties; - /** - * Reason code for MQTTV5 disconnect - */ - enum MQTTReasonCodes reasonCode; - /** - * A pointer to a callback function to be called if the disconnect successfully - * completes. Can be set to NULL, in which case no indication of successful - * completion will be received. - */ - MQTTAsync_onSuccess5* onSuccess5; - /** - * A pointer to a callback function to be called if the disconnect fails. - * Can be set to NULL, in which case no indication of unsuccessful - * completion will be received. - */ - MQTTAsync_onFailure5* onFailure5; -} MQTTAsync_disconnectOptions; - -#define MQTTAsync_disconnectOptions_initializer { {'M', 'Q', 'T', 'D'}, 1, 0, NULL, NULL, NULL, MQTTProperties_initializer, MQTTREASONCODE_SUCCESS } - - -/** - * This function attempts to disconnect the client from the MQTT - * server. In order to allow the client time to complete handling of messages - * that are in-flight when this function is called, a timeout period is - * specified. When the timeout period has expired, the client disconnects even - * if there are still outstanding message acknowledgements. - * The next time the client connects to the same server, any QoS 1 or 2 - * messages which have not completed will be retried depending on the - * cleansession settings for both the previous and the new connection (see - * MQTTAsync_connectOptions.cleansession and MQTTAsync_connect()). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param options The client delays disconnection for up to this time (in - * milliseconds) in order to allow in-flight message transfers to complete. - * @return ::MQTTASYNC_SUCCESS if the client successfully disconnects from - * the server. An error code is returned if the client was unable to disconnect - * from the server - */ -DLLExport int MQTTAsync_disconnect(MQTTAsync handle, const MQTTAsync_disconnectOptions* options); - - -/** - * This function allows the client application to test whether or not a - * client is currently connected to the MQTT server. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @return Boolean true if the client is connected, otherwise false. - */ -DLLExport int MQTTAsync_isConnected(MQTTAsync handle); - - -/** - * This function attempts to subscribe a client to a single topic, which may - * contain wildcards (see @ref wildcard). This call also specifies the - * @ref qos requested for the subscription - * (see also MQTTAsync_subscribeMany()). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param topic The subscription topic, which may include wildcards. - * @param qos The requested quality of service for the subscription. - * @param response A pointer to a response options structure. Used to set callback functions. - * @return ::MQTTASYNC_SUCCESS if the subscription request is successful. - * An error code is returned if there was a problem registering the - * subscription. - */ -DLLExport int MQTTAsync_subscribe(MQTTAsync handle, const char* topic, int qos, MQTTAsync_responseOptions* response); - - -/** - * This function attempts to subscribe a client to a list of topics, which may - * contain wildcards (see @ref wildcard). This call also specifies the - * @ref qos requested for each topic (see also MQTTAsync_subscribe()). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param count The number of topics for which the client is requesting - * subscriptions. - * @param topic An array (of length count) of pointers to - * topics, each of which may include wildcards. - * @param qos An array (of length count) of @ref qos - * values. qos[n] is the requested QoS for topic[n]. - * @param response A pointer to a response options structure. Used to set callback functions. - * @return ::MQTTASYNC_SUCCESS if the subscription request is successful. - * An error code is returned if there was a problem registering the - * subscriptions. - */ -DLLExport int MQTTAsync_subscribeMany(MQTTAsync handle, int count, char* const* topic, int* qos, MQTTAsync_responseOptions* response); - -/** - * This function attempts to remove an existing subscription made by the - * specified client. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param topic The topic for the subscription to be removed, which may - * include wildcards (see @ref wildcard). - * @param response A pointer to a response options structure. Used to set callback functions. - * @return ::MQTTASYNC_SUCCESS if the subscription is removed. - * An error code is returned if there was a problem removing the - * subscription. - */ -DLLExport int MQTTAsync_unsubscribe(MQTTAsync handle, const char* topic, MQTTAsync_responseOptions* response); - -/** - * This function attempts to remove existing subscriptions to a list of topics - * made by the specified client. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param count The number subscriptions to be removed. - * @param topic An array (of length count) of pointers to the topics of - * the subscriptions to be removed, each of which may include wildcards. - * @param response A pointer to a response options structure. Used to set callback functions. - * @return ::MQTTASYNC_SUCCESS if the subscriptions are removed. - * An error code is returned if there was a problem removing the subscriptions. - */ -DLLExport int MQTTAsync_unsubscribeMany(MQTTAsync handle, int count, char* const* topic, MQTTAsync_responseOptions* response); - - -/** - * This function attempts to publish a message to a given topic (see also - * ::MQTTAsync_sendMessage()). An ::MQTTAsync_token is issued when - * this function returns successfully. If the client application needs to - * test for successful delivery of messages, a callback should be set - * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param destinationName The topic associated with this message. - * @param payloadlen The length of the payload in bytes. - * @param payload A pointer to the byte array payload of the message. - * @param qos The @ref qos of the message. - * @param retained The retained flag for the message. - * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions. - * This is optional and can be set to NULL. - * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication. - * An error code is returned if there was a problem accepting the message. - */ -DLLExport int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen, const void* payload, int qos, - int retained, MQTTAsync_responseOptions* response); - - -/** - * This function attempts to publish a message to a given topic (see also - * MQTTAsync_publish()). An ::MQTTAsync_token is issued when - * this function returns successfully. If the client application needs to - * test for successful delivery of messages, a callback should be set - * (see ::MQTTAsync_onSuccess() and ::MQTTAsync_deliveryComplete()). - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param destinationName The topic associated with this message. - * @param msg A pointer to a valid MQTTAsync_message structure containing - * the payload and attributes of the message to be published. - * @param response A pointer to an ::MQTTAsync_responseOptions structure. Used to set callback functions. - * @return ::MQTTASYNC_SUCCESS if the message is accepted for publication. - * An error code is returned if there was a problem accepting the message. - */ -DLLExport int MQTTAsync_sendMessage(MQTTAsync handle, const char* destinationName, const MQTTAsync_message* msg, MQTTAsync_responseOptions* response); - - -/** - * This function sets a pointer to an array of tokens for - * messages that are currently in-flight (pending completion). - * - * Important note: The memory used to hold the array of tokens is - * malloc()'d in this function. The client application is responsible for - * freeing this memory when it is no longer required. - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param tokens The address of a pointer to an ::MQTTAsync_token. - * When the function returns successfully, the pointer is set to point to an - * array of tokens representing messages pending completion. The last member of - * the array is set to -1 to indicate there are no more tokens. If no tokens - * are pending, the pointer is set to NULL. - * @return ::MQTTASYNC_SUCCESS if the function returns successfully. - * An error code is returned if there was a problem obtaining the list of - * pending tokens. - */ -DLLExport int MQTTAsync_getPendingTokens(MQTTAsync handle, MQTTAsync_token **tokens); - -/** - * Tests whether a request corresponding to a token is complete. - * - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param token An ::MQTTAsync_token associated with a request. - * @return 1 if the request has been completed, 0 if not. - */ -#define MQTTASYNC_TRUE 1 -DLLExport int MQTTAsync_isComplete(MQTTAsync handle, MQTTAsync_token token); - - -/** - * Waits for a request corresponding to a token to complete. - * - * @param handle A valid client handle from a successful call to - * MQTTAsync_create(). - * @param token An ::MQTTAsync_token associated with a request. - * @param timeout the maximum time to wait for completion, in milliseconds - * @return ::MQTTASYNC_SUCCESS if the request has been completed in the time allocated, - * ::MQTTASYNC_FAILURE if not. - */ -DLLExport int MQTTAsync_waitForCompletion(MQTTAsync handle, MQTTAsync_token token, unsigned long timeout); - - -/** - * This function frees memory allocated to an MQTT message, including the - * additional memory allocated to the message payload. The client application - * calls this function when the message has been fully processed. Important - * note: This function does not free the memory allocated to a message - * topic string. It is the responsibility of the client application to free - * this memory using the MQTTAsync_free() library function. - * @param msg The address of a pointer to the ::MQTTAsync_message structure - * to be freed. - */ -DLLExport void MQTTAsync_freeMessage(MQTTAsync_message** msg); - -/** - * This function frees memory allocated by the MQTT C client library, especially the - * topic name. This is needed on Windows when the client libary and application - * program have been compiled with different versions of the C compiler. It is - * thus good policy to always use this function when freeing any MQTT C client- - * allocated memory. - * @param ptr The pointer to the client library storage to be freed. - */ -DLLExport void MQTTAsync_free(void* ptr); - -/** - * This function frees the memory allocated to an MQTT client (see - * MQTTAsync_create()). It should be called when the client is no longer - * required. - * @param handle A pointer to the handle referring to the ::MQTTAsync - * structure to be freed. - */ -DLLExport void MQTTAsync_destroy(MQTTAsync* handle); - - - -enum MQTTASYNC_TRACE_LEVELS -{ - MQTTASYNC_TRACE_MAXIMUM = 1, - MQTTASYNC_TRACE_MEDIUM, - MQTTASYNC_TRACE_MINIMUM, - MQTTASYNC_TRACE_PROTOCOL, - MQTTASYNC_TRACE_ERROR, - MQTTASYNC_TRACE_SEVERE, - MQTTASYNC_TRACE_FATAL, -}; - - -/** - * This function sets the level of trace information which will be - * returned in the trace callback. - * @param level the trace level required - */ -DLLExport void MQTTAsync_setTraceLevel(enum MQTTASYNC_TRACE_LEVELS level); - - -/** - * This is a callback function prototype which must be implemented if you want - * to receive trace information. - * @param level the trace level of the message returned - * @param message the trace message. This is a pointer to a static buffer which - * will be overwritten on each call. You must copy the data if you want to keep - * it for later. - */ -typedef void MQTTAsync_traceCallback(enum MQTTASYNC_TRACE_LEVELS level, char* message); - -/** - * This function sets the trace callback if needed. If set to NULL, - * no trace information will be returned. The default trace level is - * MQTTASYNC_TRACE_MINIMUM. - * @param callback a pointer to the function which will handle the trace information - */ -DLLExport void MQTTAsync_setTraceCallback(MQTTAsync_traceCallback* callback); - - -typedef struct -{ - const char* name; - const char* value; -} MQTTAsync_nameValue; - -/** - * This function returns version information about the library. - * no trace information will be returned. The default trace level is - * MQTTASYNC_TRACE_MINIMUM - * @return an array of strings describing the library. The last entry is a NULL pointer. - */ -DLLExport MQTTAsync_nameValue* MQTTAsync_getVersionInfo(void); - -/** - * Returns a pointer to a string representation of the error code, or NULL. - * Do not free after use. Returns NULL if the error code is unknown. - * @param code the MQTTASYNC_ return code. - * @return a static string representation of the error code. - */ -DLLExport const char* MQTTAsync_strerror(int code); - - -/** - * @cond MQTTAsync_main - * @page async Threading - * The client application runs on several threads. - * Processing of handshaking and maintaining - * the network connection is performed in the background. - * This API is thread safe: functions may be called by multiple application - * threads. - * Notifications of status and message reception are provided to the client - * application using callbacks registered with the library by the call to - * MQTTAsync_setCallbacks() (see MQTTAsync_messageArrived(), - * MQTTAsync_connectionLost() and MQTTAsync_deliveryComplete()). - * In addition, some functions allow success and failure callbacks to be set - * for individual requests, in the ::MQTTAsync_responseOptions structure. Applications - * can be written as a chain of callback functions. Note that it is a theoretically - * possible but unlikely event, that a success or failure callback could be called - * before function requesting the callback has returned. In this case the token - * delivered in the callback would not yet be known to the application program (see - * Race condition for MQTTAsync_token in MQTTAsync.c - * https://bugs.eclipse.org/bugs/show_bug.cgi?id=444093) - * - * @page auto_reconnect Automatic Reconnect - * The ability for the client library to reconnect automatically in the event - * of a connection failure was added in 1.1. The connection lost callback - * allows a flexible response to the loss of a connection, so almost any - * behaviour can be implemented in that way. Automatic reconnect does have the - * advantage of being a little simpler to use. - * - * To switch on automatic reconnect, the connect options field - * automaticReconnect should be set to non-zero. The minimum and maximum times - * before the next connection attempt can also be set, the defaults being 1 and - * 60 seconds. At each failure to reconnect, the retry interval is doubled until - * the maximum value is reached, and there it stays until the connection is - * successfully re-established whereupon it is reset. - * - * When a reconnection attempt is successful, the ::MQTTAsync_connected callback - * function is invoked, if set by calling ::MQTTAsync_setConnected. This allows - * the application to take any actions needed, such as amending subscriptions. - * - * @page offline_publish Publish While Disconnected - * This feature was not originally available because with persistence enabled, - * messages could be stored locally without ever knowing if they could be sent. - * The client application could have created the client with an erroneous broker - * address or port for instance. - * - * To enable messages to be published when the application is disconnected - * ::MQTTAsync_createWithOptions must be used instead of ::MQTTAsync_create to - * create the client object. The ::createOptions field sendWhileDisconnected - * must be set to non-zero, and the maxBufferedMessages field set as required - - * the default being 100. - * - * ::MQTTAsync_getPendingTokens can be called to return the ids of the messages - * waiting to be sent, or for which the sending process has not completed. - * - * @page wildcard Subscription wildcards - * Every MQTT message includes a topic that classifies it. MQTT servers use - * topics to determine which subscribers should receive messages published to - * the server. - * - * Consider the server receiving messages from several environmental sensors. - * Each sensor publishes its measurement data as a message with an associated - * topic. Subscribing applications need to know which sensor originally - * published each received message. A unique topic is thus used to identify - * each sensor and measurement type. Topics such as SENSOR1TEMP, - * SENSOR1HUMIDITY, SENSOR2TEMP and so on achieve this but are not very - * flexible. If additional sensors are added to the system at a later date, - * subscribing applications must be modified to receive them. - * - * To provide more flexibility, MQTT supports a hierarchical topic namespace. - * This allows application designers to organize topics to simplify their - * management. Levels in the hierarchy are delimited by the '/' character, - * such as SENSOR/1/HUMIDITY. Publishers and subscribers use these - * hierarchical topics as already described. - * - * For subscriptions, two wildcard characters are supported: - *
    - *
  • A '#' character represents a complete sub-tree of the hierarchy and - * thus must be the last character in a subscription topic string, such as - * SENSOR/#. This will match any topic starting with SENSOR/, such as - * SENSOR/1/TEMP and SENSOR/2/HUMIDITY.
  • - *
  • A '+' character represents a single level of the hierarchy and is - * used between delimiters. For example, SENSOR/+/TEMP will match - * SENSOR/1/TEMP and SENSOR/2/TEMP.
  • - *
- * Publishers are not allowed to use the wildcard characters in their topic - * names. - * - * Deciding on your topic hierarchy is an important step in your system design. - * - * @page qos Quality of service - * The MQTT protocol provides three qualities of service for delivering - * messages between clients and servers: "at most once", "at least once" and - * "exactly once". - * - * Quality of service (QoS) is an attribute of an individual message being - * published. An application sets the QoS for a specific message by setting the - * MQTTAsync_message.qos field to the required value. - * - * A subscribing client can set the maximum quality of service a server uses - * to send messages that match the client subscriptions. The - * MQTTAsync_subscribe() and MQTTAsync_subscribeMany() functions set this - * maximum. The QoS of a message forwarded to a subscriber thus might be - * different to the QoS given to the message by the original publisher. - * The lower of the two values is used to forward a message. - * - * The three levels are: - * - * QoS0, At most once: The message is delivered at most once, or it - * may not be delivered at all. Its delivery across the network is not - * acknowledged. The message is not stored. The message could be lost if the - * client is disconnected, or if the server fails. QoS0 is the fastest mode of - * transfer. It is sometimes called "fire and forget". - * - * The MQTT protocol does not require servers to forward publications at QoS0 - * to a client. If the client is disconnected at the time the server receives - * the publication, the publication might be discarded, depending on the - * server implementation. - * - * QoS1, At least once: The message is always delivered at least once. - * It might be delivered multiple times if there is a failure before an - * acknowledgment is received by the sender. The message must be stored - * locally at the sender, until the sender receives confirmation that the - * message has been published by the receiver. The message is stored in case - * the message must be sent again. - * - * QoS2, Exactly once: The message is always delivered exactly once. - * The message must be stored locally at the sender, until the sender receives - * confirmation that the message has been published by the receiver. The - * message is stored in case the message must be sent again. QoS2 is the - * safest, but slowest mode of transfer. A more sophisticated handshaking - * and acknowledgement sequence is used than for QoS1 to ensure no duplication - * of messages occurs. - - - * @page publish Publication example -@code -#include -#include -#include -#include "MQTTAsync.h" - -#define ADDRESS "tcp://localhost:1883" -#define CLIENTID "ExampleClientPub" -#define TOPIC "MQTT Examples" -#define PAYLOAD "Hello World!" -#define QOS 1 -#define TIMEOUT 10000L - -volatile MQTTAsync_token deliveredtoken; - -int finished = 0; - -void connlost(void *context, char *cause) -{ - MQTTAsync client = (MQTTAsync)context; - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - int rc; - - printf("\nConnection lost\n"); - printf(" cause: %s\n", cause); - - printf("Reconnecting\n"); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start connect, return code %d\n", rc); - finished = 1; - } -} - - -void onDisconnect(void* context, MQTTAsync_successData* response) -{ - printf("Successful disconnection\n"); - finished = 1; -} - - -void onSend(void* context, MQTTAsync_successData* response) -{ - MQTTAsync client = (MQTTAsync)context; - MQTTAsync_disconnectOptions opts = MQTTAsync_disconnectOptions_initializer; - int rc; - - printf("Message with token value %d delivery confirmed\n", response->token); - - opts.onSuccess = onDisconnect; - opts.context = client; - - if ((rc = MQTTAsync_disconnect(client, &opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start sendMessage, return code %d\n", rc); - exit(EXIT_FAILURE); - } -} - - -void onConnectFailure(void* context, MQTTAsync_failureData* response) -{ - printf("Connect failed, rc %d\n", response ? response->code : 0); - finished = 1; -} - - -void onConnect(void* context, MQTTAsync_successData* response) -{ - MQTTAsync client = (MQTTAsync)context; - MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; - MQTTAsync_message pubmsg = MQTTAsync_message_initializer; - int rc; - - printf("Successful connection\n"); - - opts.onSuccess = onSend; - opts.context = client; - - pubmsg.payload = PAYLOAD; - pubmsg.payloadlen = strlen(PAYLOAD); - pubmsg.qos = QOS; - pubmsg.retained = 0; - deliveredtoken = 0; - - if ((rc = MQTTAsync_sendMessage(client, TOPIC, &pubmsg, &opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start sendMessage, return code %d\n", rc); - exit(EXIT_FAILURE); - } -} - - -int main(int argc, char* argv[]) -{ - MQTTAsync client; - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - MQTTAsync_message pubmsg = MQTTAsync_message_initializer; - MQTTAsync_token token; - int rc; - - MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); - - MQTTAsync_setCallbacks(client, NULL, connlost, NULL, NULL); - - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - conn_opts.onSuccess = onConnect; - conn_opts.onFailure = onConnectFailure; - conn_opts.context = client; - if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start connect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - - printf("Waiting for publication of %s\n" - "on topic %s for client with ClientID: %s\n", - PAYLOAD, TOPIC, CLIENTID); - while (!finished) - #if defined(WIN32) || defined(WIN64) - Sleep(100); - #else - usleep(10000L); - #endif - - MQTTAsync_destroy(&client); - return rc; -} - - * @endcode - * @page subscribe Subscription example -@code -#include -#include -#include -#include "MQTTAsync.h" - -#define ADDRESS "tcp://localhost:1883" -#define CLIENTID "ExampleClientSub" -#define TOPIC "MQTT Examples" -#define PAYLOAD "Hello World!" -#define QOS 1 -#define TIMEOUT 10000L - -volatile MQTTAsync_token deliveredtoken; - -int disc_finished = 0; -int subscribed = 0; -int finished = 0; - -void connlost(void *context, char *cause) -{ - MQTTAsync client = (MQTTAsync)context; - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - int rc; - - printf("\nConnection lost\n"); - printf(" cause: %s\n", cause); - - printf("Reconnecting\n"); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start connect, return code %d\n", rc); - finished = 1; - } -} - - -int msgarrvd(void *context, char *topicName, int topicLen, MQTTAsync_message *message) -{ - int i; - char* payloadptr; - - printf("Message arrived\n"); - printf(" topic: %s\n", topicName); - printf(" message: "); - - payloadptr = message->payload; - for(i=0; ipayloadlen; i++) - { - putchar(*payloadptr++); - } - putchar('\n'); - MQTTAsync_freeMessage(&message); - MQTTAsync_free(topicName); - return 1; -} - - -void onDisconnect(void* context, MQTTAsync_successData* response) -{ - printf("Successful disconnection\n"); - disc_finished = 1; -} - - -void onSubscribe(void* context, MQTTAsync_successData* response) -{ - printf("Subscribe succeeded\n"); - subscribed = 1; -} - -void onSubscribeFailure(void* context, MQTTAsync_failureData* response) -{ - printf("Subscribe failed, rc %d\n", response ? response->code : 0); - finished = 1; -} - - -void onConnectFailure(void* context, MQTTAsync_failureData* response) -{ - printf("Connect failed, rc %d\n", response ? response->code : 0); - finished = 1; -} - - -void onConnect(void* context, MQTTAsync_successData* response) -{ - MQTTAsync client = (MQTTAsync)context; - MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; - MQTTAsync_message pubmsg = MQTTAsync_message_initializer; - int rc; - - printf("Successful connection\n"); - - printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n" - "Press Q to quit\n\n", TOPIC, CLIENTID, QOS); - opts.onSuccess = onSubscribe; - opts.onFailure = onSubscribeFailure; - opts.context = client; - - deliveredtoken = 0; - - if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start subscribe, return code %d\n", rc); - exit(EXIT_FAILURE); - } -} - - -int main(int argc, char* argv[]) -{ - MQTTAsync client; - MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer; - MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer; - MQTTAsync_message pubmsg = MQTTAsync_message_initializer; - MQTTAsync_token token; - int rc; - int ch; - - MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL); - - MQTTAsync_setCallbacks(client, NULL, connlost, msgarrvd, NULL); - - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - conn_opts.onSuccess = onConnect; - conn_opts.onFailure = onConnectFailure; - conn_opts.context = client; - if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start connect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - - while (!subscribed) - #if defined(WIN32) || defined(WIN64) - Sleep(100); - #else - usleep(10000L); - #endif - - if (finished) - goto exit; - - do - { - ch = getchar(); - } while (ch!='Q' && ch != 'q'); - - disc_opts.onSuccess = onDisconnect; - if ((rc = MQTTAsync_disconnect(client, &disc_opts)) != MQTTASYNC_SUCCESS) - { - printf("Failed to start disconnect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - while (!disc_finished) - #if defined(WIN32) || defined(WIN64) - Sleep(100); - #else - usleep(10000L); - #endif - -exit: - MQTTAsync_destroy(&client); - return rc; -} - - * @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 - */ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTClient.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTClient.h deleted file mode 100644 index 518dbbd..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTClient.h +++ /dev/null @@ -1,1670 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - * Ian Craggs - multiple server connection support - * Ian Craggs - MQTT 3.1.1 support - * Ian Craggs - remove const from eyecatchers #168 - *******************************************************************************/ - -/** - * @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. This API is thread safe: functions may be called by multiple application - * threads, with the exception of ::MQTTClient_yield and ::MQTTClient_receive, which are intended - * for single threaded environments only. - * - * @endcond - * @cond MQTTClient_main - * @mainpage MQTT Client library for C - * © Copyright IBM Corp. 2009, 2018 - * - * @brief An MQTT client library in C. - * - * These pages describe the original more synchronous API which might be - * 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. - * The MQTTClient API is not thread safe, whereas the MQTTAsync API is. - * - * An MQTT client application connects to MQTT-capable servers. - * A typical client is responsible for collecting information from a telemetry - * device and publishing the information to the server. It can also subscribe - * to topics, receive messages, and use this information to control the - * telemetry device. - * - * MQTT clients implement the published MQTT v3 protocol. You can write your own - * 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, 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 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).
  • - *
  • Subscribe to any topics the client needs to receive
  • - *
  • Repeat until finished:
  • - *
      - *
    • Publish any messages the client needs to
    • - *
    • Handle any incoming messages
    • - *
    - *
  • Disconnect the client
  • - *
  • Free any memory being used by the client
  • - *
- * Some simple examples are shown here: - *
    - *
  • @ref pubsync
  • - *
  • @ref pubasync
  • - *
  • @ref subasync
  • - *
- * Additional information about important concepts is provided here: - *
    - *
  • @ref async
  • - *
  • @ref wildcard
  • - *
  • @ref qos
  • - *
  • @ref tracing
  • - *
- * @endcond - */ - -/* -/// @cond EXCLUDE -*/ -#if !defined(MQTTCLIENT_H) -#define MQTTCLIENT_H - -#if defined(__cplusplus) - extern "C" { -#endif - -#if defined(WIN32) || defined(WIN64) - #define DLLImport __declspec(dllimport) - #define DLLExport __declspec(dllexport) -#else - #define DLLImport extern - #define DLLExport __attribute__ ((visibility ("default"))) -#endif - -#include -/* -/// @endcond -*/ - -#include "MQTTProperties.h" -#include "MQTTReasonCodes.h" -#include "MQTTSubscribeOpts.h" -#if !defined(NO_PERSISTENCE) -#include "MQTTClientPersistence.h" -#endif - -/** - * Return code: No error. Indicates successful completion of an MQTT client - * operation. - */ -#define MQTTCLIENT_SUCCESS 0 -/** - * Return code: A generic error code indicating the failure of an MQTT client - * operation. - */ -#define MQTTCLIENT_FAILURE -1 - -/* error code -2 is MQTTCLIENT_PERSISTENCE_ERROR */ - -/** - * Return code: The client is disconnected. - */ -#define MQTTCLIENT_DISCONNECTED -3 -/** - * Return code: The maximum number of messages allowed to be simultaneously - * in-flight has been reached. - */ -#define MQTTCLIENT_MAX_MESSAGES_INFLIGHT -4 -/** - * Return code: An invalid UTF-8 string has been detected. - */ -#define MQTTCLIENT_BAD_UTF8_STRING -5 -/** - * Return code: A NULL parameter has been supplied when this is invalid. - */ -#define MQTTCLIENT_NULL_PARAMETER -6 -/** - * Return code: The topic has been truncated (the topic string includes - * embedded NULL characters). String functions will not access the full topic. - * Use the topic length value to access the full topic. - */ -#define MQTTCLIENT_TOPICNAME_TRUNCATED -7 -/** - * Return code: A structure parameter does not have the correct eyecatcher - * and version number. - */ -#define MQTTCLIENT_BAD_STRUCTURE -8 -/** - * Return code: A QoS value that falls outside of the acceptable range (0,1,2) - */ -#define MQTTCLIENT_BAD_QOS -9 -/** - * Return code: Attempting SSL connection using non-SSL version of library - */ -#define MQTTCLIENT_SSL_NOT_SUPPORTED -10 - /** - * Return code: unrecognized MQTT version - */ - #define MQTTCLIENT_BAD_MQTT_VERSION -11 -/** - * Return code: protocol prefix in serverURI should be tcp:// or ssl:// - */ -#define MQTTCLIENT_BAD_PROTOCOL -14 - /** - * Return code: option not applicable to the requested version of MQTT - */ - #define MQTTCLIENT_BAD_MQTT_OPTION -15 - /** - * Return code: call not applicable to the requested version of MQTT - */ - #define MQTTCLIENT_WRONG_MQTT_VERSION -16 - - -/** - * Default MQTT version to connect with. Use 3.1.1 then fall back to 3.1 - */ -#define MQTTVERSION_DEFAULT 0 -/** - * MQTT version to connect with: 3.1 - */ -#define MQTTVERSION_3_1 3 -/** - * MQTT version to connect with: 3.1.1 - */ -#define MQTTVERSION_3_1_1 4 - /** - * MQTT version to connect with: 5 - */ - #define MQTTVERSION_5 5 -/** - * Bad return code from subscribe, as defined in the 3.1.1 specification - */ -#define MQTT_BAD_SUBSCRIBE 0x80 - -/** - * Initialization options - */ -typedef struct -{ - /** The eyecatcher for this structure. Must be MQTG. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 */ - int struct_version; - /** 1 = we do openssl init, 0 = leave it to the application */ - int do_openssl_init; -} MQTTClient_init_options; - -#define MQTTClient_init_options_initializer { {'M', 'Q', 'T', 'G'}, 0, 0 } - -/** - * Global init of mqtt library. Call once on program start to set global behaviour. - * do_openssl_init - if mqtt library should initialize OpenSSL (1) or rely on the caller to do it before using the library (0) - */ -DLLExport void MQTTClient_global_init(MQTTClient_init_options* inits); - -/** - * A handle representing an MQTT client. A valid client handle is available - * following a successful call to MQTTClient_create(). - */ -typedef void* MQTTClient; -/** - * A value representing an MQTT message. A delivery token is returned to the - * client application when a message is published. The token can then be used to - * check that the message was successfully delivered to its destination (see - * MQTTClient_publish(), - * MQTTClient_publishMessage(), - * MQTTClient_deliveryComplete(), - * MQTTClient_waitForCompletion() and - * MQTTClient_getPendingDeliveryTokens()). - */ -typedef int MQTTClient_deliveryToken; -typedef int MQTTClient_token; - -/** - * A structure representing the payload and attributes of an MQTT message. The - * message topic is not part of this structure (see MQTTClient_publishMessage(), - * MQTTClient_publish(), MQTTClient_receive(), MQTTClient_freeMessage() - * and MQTTClient_messageArrived()). - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTM. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 - * 0 indicates no message properties */ - int struct_version; - /** The length of the MQTT message payload in bytes. */ - int payloadlen; - /** A pointer to the payload of the MQTT message. */ - void* payload; - /** - * The quality of service (QoS) assigned to the message. - * There are three levels of QoS: - *
- *
QoS0
- *
Fire and forget - the message may not be delivered
- *
QoS1
- *
At least once - the message will be delivered, but may be - * delivered more than once in some circumstances.
- *
QoS2
- *
Once and one only - the message will be delivered exactly once.
- *
- */ - int qos; - /** - * The retained flag serves two purposes depending on whether the message - * it is associated with is being published or received. - * - * retained = true
- * For messages being published, a true setting indicates that the MQTT - * server should retain a copy of the message. The message will then be - * transmitted to new subscribers to a topic that matches the message topic. - * For subscribers registering a new subscription, the flag being true - * indicates that the received message is not a new one, but one that has - * been retained by the MQTT server. - * - * retained = false
- * For publishers, this indicates that this message should not be retained - * by the MQTT server. For subscribers, a false setting indicates this is - * a normal message, received as a result of it being published to the - * server. - */ - int retained; - /** - * The dup flag indicates whether or not this message is a duplicate. - * It is only meaningful when receiving QoS1 messages. When true, the - * client application should take appropriate action to deal with the - * duplicate message. - */ - int dup; - /** The message identifier is normally reserved for internal use by the - * MQTT client and server. - */ - int msgid; - /** - * The MQTT V5 properties associated with the message. - */ - MQTTProperties properties; -} MQTTClient_message; - -#define MQTTClient_message_initializer { {'M', 'Q', 'T', 'M'}, 1, 0, NULL, 0, 0, 0, 0, MQTTProperties_initializer } - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * receipt of messages. The function is registered with the client library by - * passing it as an argument to MQTTClient_setCallbacks(). It is - * called by the client library when a new message that matches a client - * subscription has been received from the server. This function is executed on - * a separate thread to the one on which the client application is running. - * @param context A pointer to the context value originally passed to - * MQTTClient_setCallbacks(), which contains any application-specific context. - * @param topicName The topic associated with the received message. - * @param topicLen The length of the topic if there are one - * more NULL characters embedded in topicName, otherwise topicLen - * is 0. If topicLen is 0, the value returned by strlen(topicName) - * can be trusted. If topicLen is greater than 0, the full topic name - * can be retrieved by accessing topicName as a byte array of length - * topicLen. - * @param message The MQTTClient_message structure for the received message. - * This structure contains the message payload and attributes. - * @return This function must return a boolean value indicating whether or not - * the message has been safely received by the client application. Returning - * true indicates that the message has been successfully handled. - * Returning false indicates that there was a problem. In this - * case, the client library will reinvoke MQTTClient_messageArrived() to - * attempt to deliver the message to the application again. - */ -typedef int MQTTClient_messageArrived(void* context, char* topicName, int topicLen, MQTTClient_message* message); - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of delivery of messages. The function is registered with the - * client library by passing it as an argument to MQTTClient_setCallbacks(). - * It is called by the client library after the client application has - * published a message to the server. It indicates that the necessary - * handshaking and acknowledgements for the requested quality of service (see - * MQTTClient_message.qos) have been completed. This function is executed on a - * separate thread to the one on which the client application is running. - * Note:MQTTClient_deliveryComplete() is not called when messages are - * published at QoS0. - * @param context A pointer to the context value originally passed to - * MQTTClient_setCallbacks(), which contains any application-specific context. - * @param dt The ::MQTTClient_deliveryToken associated with - * the published message. Applications can check that all messages have been - * correctly published by matching the delivery tokens returned from calls to - * MQTTClient_publish() and MQTTClient_publishMessage() with the tokens passed - * to this callback. - */ -typedef void MQTTClient_deliveryComplete(void* context, MQTTClient_deliveryToken dt); - -/** - * This is a callback function. The client application - * must provide an implementation of this function to enable asynchronous - * notification of the loss of connection to the server. The function is - * registered with the client library by passing it as an argument to - * MQTTClient_setCallbacks(). It is called by the client library if the client - * loses its connection to the server. The client application must take - * appropriate action, such as trying to reconnect or reporting the problem. - * This function is executed on a separate thread to the one on which the - * client application is running. - * @param context A pointer to the context value originally passed to - * MQTTClient_setCallbacks(), which contains any application-specific context. - * @param cause The reason for the disconnection. - * Currently, cause is always set to NULL. - */ -typedef void MQTTClient_connectionLost(void* context, char* cause); - -/** - * This function sets the callback functions for a specific client. - * If your client application doesn't use a particular callback, set the - * relevant parameter to NULL. Calling MQTTClient_setCallbacks() puts the - * client into multi-threaded mode. Any necessary message acknowledgements and - * status communications are handled in the background without any intervention - * from the client application. See @ref async for more information. - * - * Note: The MQTT client must be disconnected when this function is - * called. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to each of the callback functions to - * provide access to the context information in the callback. - * @param cl A pointer to an MQTTClient_connectionLost() callback - * function. You can set this to NULL if your application doesn't handle - * disconnections. - * @param ma A pointer to an MQTTClient_messageArrived() callback - * function. This callback function must be specified when you call - * MQTTClient_setCallbacks(). - * @param dc A pointer to an MQTTClient_deliveryComplete() callback - * function. You can set this to NULL if your application publishes - * synchronously or if you do not want to check for successful delivery. - * @return ::MQTTCLIENT_SUCCESS if the callbacks were correctly set, - * ::MQTTCLIENT_FAILURE if an error occurred. - */ -DLLExport int MQTTClient_setCallbacks(MQTTClient handle, void* context, MQTTClient_connectionLost* cl, - MQTTClient_messageArrived* ma, MQTTClient_deliveryComplete* dc); - - -/** - * This is a callback function, which will be called when the a disconnect - * packet is received from the server. This applies to MQTT V5 and above only. - * @param context A pointer to the context value originally passed to - * ::MQTTAsync_setDisconnected(), which contains any application-specific context. - * @param properties The MQTT V5 properties received with the disconnect, if any. - * @param reasonCode The MQTT V5 reason code received with the disconnect. - * Currently, cause is always set to NULL. - */ -typedef void MQTTClient_disconnected(void* context, MQTTProperties* properties, - enum MQTTReasonCodes reasonCode); - -/** - * Sets the MQTTClient_disconnected() callback function for a client. This will be called - * if a disconnect packet is received from the server. Only valid for MQTT V5 and above. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param context A pointer to any application-specific context. The - * the context pointer is passed to each of the callback functions to - * provide access to the context information in the callback. - * @param co A pointer to an MQTTClient_disconnected() callback - * function. NULL removes the callback setting. - * @return ::MQTTCLIENT_SUCCESS if the callbacks were correctly set, - * ::MQTTCLIENT_FAILURE if an error occurred. - */ -DLLExport int MQTTClient_setDisconnected(MQTTClient handle, void* context, MQTTClient_disconnected* co); - -/** - * This is a callback function, the MQTT V5 version of MQTTClient_deliveryComplete(). - * The client application - * must provide an implementation of this function to enable asynchronous - * notification of the completed delivery of messages. - * It is called by the client library after the client application has - * published a message to the server. It indicates that the necessary - * handshaking and acknowledgements for the requested quality of service (see - * MQTTClient_message.qos) have been completed. This function is executed on a - * separate thread to the one on which the client application is running. - * Note: It is not called when messages are published at QoS0. - * @param context A pointer to the context value originally passed to - * MQTTClient_setCallbacks(), which contains any application-specific context. - * @param dt The ::MQTTClient_deliveryToken associated with - * the published message. Applications can check that all messages have been - * correctly published by matching the delivery tokens returned from calls to - * MQTTClient_publish() and MQTTClient_publishMessage() with the tokens passed - * to this callback. - * @param packet_type the last received packet type for this completion. For QoS 1 - * always PUBACK. For QoS 2 could be PUBREC or PUBCOMP. - * @param properties the MQTT V5 properties returned with the last packet from the server - * @param reasonCode the reason code returned from the server - */ -typedef void MQTTClient_published(void* context, int dt, int packet_type, MQTTProperties* properties, - enum MQTTReasonCodes reasonCode); - -DLLExport int MQTTClient_setPublished(MQTTClient handle, void* context, MQTTClient_published* co); - -/** - * This function creates an MQTT client ready for connection to the - * specified server and using the specified persistent storage (see - * MQTTClient_persistence). See also MQTTClient_destroy(). - * @param handle A pointer to an ::MQTTClient handle. The handle is - * populated with a valid client reference following a successful return from - * this function. - * @param serverURI A null-terminated string specifying the server to - * which the client will connect. It takes the form protocol://host:port. - * Currently, 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. - * @param clientId The client identifier passed to the server when the - * client connects to it. It is a null-terminated UTF-8 encoded string. - * @param persistence_type The type of persistence to be used by the client: - *
- * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or - * system on which the client is running fails or is switched off, the current - * state of any in-flight messages is lost and some messages may not be - * delivered even at QoS1 and QoS2. - *
- * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based) - * persistence mechanism. Status about in-flight messages is held in persistent - * storage and provides some protection against message loss in the case of - * unexpected failure. - *
- * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence - * implementation. Using this type of persistence gives control of the - * persistence mechanism to the application. The application has to implement - * the MQTTClient_persistence interface. - * @param persistence_context If the application uses - * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should - * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it - * should be set to the location of the persistence directory (if set - * to NULL, the persistence directory used is the working directory). - * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this - * argument to point to a valid MQTTClient_persistence structure. - * @return ::MQTTCLIENT_SUCCESS if the client is successfully created, otherwise - * an error code is returned. - */ -DLLExport int MQTTClient_create(MQTTClient* handle, const char* serverURI, const char* clientId, - int persistence_type, void* persistence_context); - -typedef struct -{ - /** The eyecatcher for this structure. must be MQCO. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 */ - int struct_version; - /** Whether the MQTT version is 3.1, 3.1.1, or 5. To use V5, this must be set. - * MQTT V5 has to be chosen here, because during the create call the message persistence - * is initialized, and we want to know whether the format of any persisted messages - * is appropriate for the MQTT version we are going to connect with. Selecting 3.1 or - * 3.1.1 and attempting to read 5.0 persisted messages will result in an error on create. */ - int MQTTVersion; -} MQTTClient_createOptions; - -#define MQTTClient_createOptions_initializer { {'M', 'Q', 'C', 'O'}, MQTTVERSION_DEFAULT } - -/** - * A version of :MQTTClient_create() with additional options. - * This function creates an MQTT client ready for connection to the - * specified server and using the specified persistent storage (see - * MQTTClient_persistence). See also MQTTClient_destroy(). - * @param handle A pointer to an ::MQTTClient handle. The handle is - * populated with a valid client reference following a successful return from - * this function. - * @param serverURI A null-terminated string specifying the server to - * which the client will connect. It takes the form protocol://host:port. - * Currently, 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. - * @param clientId The client identifier passed to the server when the - * client connects to it. It is a null-terminated UTF-8 encoded string. - * @param persistence_type The type of persistence to be used by the client: - *
- * ::MQTTCLIENT_PERSISTENCE_NONE: Use in-memory persistence. If the device or - * system on which the client is running fails or is switched off, the current - * state of any in-flight messages is lost and some messages may not be - * delivered even at QoS1 and QoS2. - *
- * ::MQTTCLIENT_PERSISTENCE_DEFAULT: Use the default (file system-based) - * persistence mechanism. Status about in-flight messages is held in persistent - * storage and provides some protection against message loss in the case of - * unexpected failure. - *
- * ::MQTTCLIENT_PERSISTENCE_USER: Use an application-specific persistence - * implementation. Using this type of persistence gives control of the - * persistence mechanism to the application. The application has to implement - * the MQTTClient_persistence interface. - * @param persistence_context If the application uses - * ::MQTTCLIENT_PERSISTENCE_NONE persistence, this argument is unused and should - * be set to NULL. For ::MQTTCLIENT_PERSISTENCE_DEFAULT persistence, it - * should be set to the location of the persistence directory (if set - * to NULL, the persistence directory used is the working directory). - * Applications that use ::MQTTCLIENT_PERSISTENCE_USER persistence set this - * argument to point to a valid MQTTClient_persistence structure. - * @param options additional options for the create. - * @return ::MQTTCLIENT_SUCCESS if the client is successfully created, otherwise - * an error code is returned. - */ -DLLExport int MQTTClient_createWithOptions(MQTTClient* handle, const char* serverURI, const char* clientId, - int persistence_type, void* persistence_context, MQTTClient_createOptions* options); - -/** - * MQTTClient_willOptions defines the MQTT "Last Will and Testament" (LWT) settings for - * the client. In the event that a client unexpectedly loses its connection to - * the server, the server publishes the LWT message to the LWT topic on - * behalf of the client. This allows other clients (subscribed to the LWT topic) - * to be made aware that the client has disconnected. To enable the LWT - * function for a specific client, a valid pointer to an MQTTClient_willOptions - * structure is passed in the MQTTClient_connectOptions structure used in the - * MQTTClient_connect() call that connects the client to the server. The pointer - * to MQTTClient_willOptions can be set to NULL if the LWT function is not - * required. - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTW. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 or 1 - 0 means there is no binary payload option - */ - int struct_version; - /** The LWT topic to which the LWT message will be published. */ - const char* topicName; - /** The LWT payload in string form. */ - const char* message; - /** - * The retained flag for the LWT message (see MQTTClient_message.retained). - */ - int retained; - /** - * The quality of service setting for the LWT message (see - * MQTTClient_message.qos and @ref qos). - */ - int qos; - /** The LWT payload in binary form. This is only checked and used if the message option is NULL */ - struct - { - int len; /**< binary payload length */ - const void* data; /**< binary payload data */ - } payload; -} MQTTClient_willOptions; - -#define MQTTClient_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 1, NULL, NULL, 0, 0, {0, NULL} } - -#define MQTT_SSL_VERSION_DEFAULT 0 -#define MQTT_SSL_VERSION_TLS_1_0 1 -#define MQTT_SSL_VERSION_TLS_1_1 2 -#define MQTT_SSL_VERSION_TLS_1_2 3 - -/** -* MQTTClient_sslProperties defines the settings to establish an SSL/TLS connection using the -* OpenSSL library. It covers the following scenarios: -* - Server authentication: The client needs the digital certificate of the server. It is included -* in a store containting trusted material (also known as "trust store"). -* - Mutual authentication: Both client and server are authenticated during the SSL handshake. In -* addition to the digital certificate of the server in a trust store, the client will need its own -* digital certificate and the private key used to sign its digital certificate stored in a "key store". -* - Anonymous connection: Both client and server do not get authenticated and no credentials are needed -* to establish an SSL connection. Note that this scenario is not fully secure since it is subject to -* man-in-the-middle attacks. -*/ -typedef struct -{ - /** The eyecatcher for this structure. Must be MQTS */ - char struct_id[4]; - /** The version number of this structure. Must be 0, or 1 to enable TLS version selection. */ - int struct_version; - - /** The file in PEM format containing the public digital certificates trusted by the client. */ - const char* trustStore; - - /** The file in PEM format containing the public certificate chain of the client. It may also include - * the client's private key. - */ - const char* keyStore; - - /** If not included in the sslKeyStore, this setting points to the file in PEM format containing - * the client's private key. - */ - const char* privateKey; - /** The password to load the client's privateKey if encrypted. */ - const char* privateKeyPassword; - - /** - * The list of cipher suites that the client will present to the server during the SSL handshake. For a - * full explanation of the cipher list format, please see the OpenSSL on-line documentation: - * http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT - * If this setting is ommitted, its default value will be "ALL", that is, all the cipher suites -excluding - * those offering no encryption- will be considered. - * This setting can be used to set an SSL anonymous connection ("aNULL" string value, for instance). - */ - const char* enabledCipherSuites; - - /** True/False option to enable verification of the server certificate **/ - int enableServerCertAuth; - - /** The SSL/TLS version to use. Specify one of MQTT_SSL_VERSION_DEFAULT (0), - * MQTT_SSL_VERSION_TLS_1_0 (1), MQTT_SSL_VERSION_TLS_1_1 (2) or MQTT_SSL_VERSION_TLS_1_2 (3). - * Only used if struct_version is >= 1. - */ - int sslVersion; - - /** - * Whether to carry out post-connect checks, including that a certificate - * matches the given host name. - * Exists only if struct_version >= 2 - */ - int verify; - - /** - * From the OpenSSL documentation: - * If CApath is not NULL, it points to a directory containing CA certificates in PEM format. - * Exists only if struct_version >= 2 - */ - const char* CApath; - - /** - * Callback function for OpenSSL error handler ERR_print_errors_cb - * Exists only if struct_version >= 3 - */ - int (*ssl_error_cb) (const char *str, size_t len, void *u); - - /** - * Application-specific contex for OpenSSL error handler ERR_print_errors_cb - * Exists only if struct_version >= 3 - */ - void* ssl_error_context; - -} MQTTClient_SSLOptions; - -#define MQTTClient_SSLOptions_initializer { {'M', 'Q', 'T', 'S'}, 3, NULL, NULL, NULL, NULL, NULL, 1, MQTT_SSL_VERSION_DEFAULT, 0, NULL, NULL, NULL } - -/** - * MQTTClient_connectOptions defines several settings that control the way the - * client connects to an MQTT server. - * - * Note: Default values are not defined for members of - * MQTTClient_connectOptions so it is good practice to specify all settings. - * If the MQTTClient_connectOptions structure is defined as an automatic - * variable, all members are set to random values and thus must be set by the - * client application. If the MQTTClient_connectOptions structure is defined - * as a static variable, initialization (in compliant compilers) sets all - * values to 0 (NULL for pointers). A #keepAliveInterval setting of 0 prevents - * correct operation of the client and so you must at least set a value - * for #keepAliveInterval. - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTC. */ - char struct_id[4]; - /** The version number of this structure. Must be 0, 1, 2, 3, 4, 5 or 6. - * 0 signifies no SSL options and no serverURIs - * 1 signifies no serverURIs - * 2 signifies no MQTTVersion - * 3 signifies no returned values - * 4 signifies no binary password option - * 5 signifies no maxInflightMessages and cleanstart - */ - 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. - */ - 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. - */ - 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. - */ - 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. - */ - MQTTClient_willOptions* will; - /** - * MQTT servers that support the MQTT v3.1.1 protocol provide authentication - * and authorisation by user name and password. This is the user name - * parameter. - */ - const char* username; - /** - * MQTT servers that support the MQTT v3.1.1 protocol provide authentication - * and authorisation by user name and password. This is the password - * parameter. - */ - const char* password; - /** - * The time interval in seconds to allow a connect to complete. - */ - int connectTimeout; - /** - * The time interval in seconds after which unacknowledged publish requests are - * retried during a TCP session. With MQTT 3.1.1 and later, retries are - * not required except on reconnect. 0 turns off in-session retries, and is the - * recommended setting. Adding retries to an already overloaded network only - * exacerbates the problem. - */ - 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. - */ - MQTTClient_SSLOptions* ssl; - /** - * The number of entries in the optional serverURIs array. Defaults to 0. - */ - int serverURIcount; - /** - * 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* const* serverURIs; - /** - * Sets the version of MQTT to be used on the connect. - * MQTTVERSION_DEFAULT (0) = default: start with 3.1.1, and if that fails, fall back to 3.1 - * MQTTVERSION_3_1 (3) = only try version 3.1 - * MQTTVERSION_3_1_1 (4) = only try version 3.1.1 - * MQTTVERSION_5 (5) = only try version 5.0 - */ - int MQTTVersion; - /** - * Returned from the connect when the MQTT version used to connect is 3.1.1 - */ - struct - { - const char* serverURI; /**< the serverURI connected to */ - int MQTTVersion; /**< the MQTT version used to connect with */ - int sessionPresent; /**< if the MQTT version is 3.1.1, the value of sessionPresent returned in the connack */ - } returned; - /** - * Optional binary password. Only checked and used if the password option is NULL - */ - struct - { - int len; /**< binary password length */ - const void* data; /**< binary password data */ - } binarypwd; - /** - * The maximum number of messages in flight - */ - int maxInflightMessages; - /* - * MQTT V5 clean start flag. Only clears state at the beginning of the session. - */ - int cleanstart; -} MQTTClient_connectOptions; - -#define MQTTClient_connectOptions_initializer { {'M', 'Q', 'T', 'C'}, 6, 60, 1, 1, NULL, NULL, NULL, 30, 0, NULL, 0, NULL, MQTTVERSION_DEFAULT, {NULL, 0, 0}, {0, NULL}, -1, 0} - -#define MQTTClient_connectOptions_initializer5 { {'M', 'Q', 'T', 'C'}, 6, 60, 0, 1, NULL, NULL, NULL, 30, 0, NULL, 0, NULL, MQTTVERSION_5, {NULL, 0, 0}, {0, NULL}, -1, 1} - -/** - * MQTTClient_libraryInfo is used to store details relating to the currently used - * library such as the version in use, the time it was built and relevant openSSL - * options. - * There is one static instance of this struct in MQTTClient.c - */ - -typedef struct -{ - const char* name; - const char* value; -} MQTTClient_nameValue; - -/** - * This function returns version information about the library. - * no trace information will be returned. - * @return an array of strings describing the library. The last entry is a NULL pointer. - */ -DLLExport MQTTClient_nameValue* MQTTClient_getVersionInfo(void); - -/** - * This function attempts to connect a previously-created client (see - * MQTTClient_create()) to an MQTT server using the specified options. If you - * want to enable asynchronous message and status notifications, you must call - * MQTTClient_setCallbacks() prior to MQTTClient_connect(). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param options A pointer to a valid MQTTClient_connectOptions - * structure. - * @return ::MQTTCLIENT_SUCCESS if the client successfully connects to the - * server. An error code is returned if the client was unable to connect to - * the server. - * Error codes greater than 0 are returned by the MQTT protocol:

- * 1: Connection refused: Unacceptable protocol version
- * 2: Connection refused: Identifier rejected
- * 3: Connection refused: Server unavailable
- * 4: Connection refused: Bad user name or password
- * 5: Connection refused: Not authorized
- * 6-255: Reserved for future use
- */ -DLLExport int MQTTClient_connect(MQTTClient handle, MQTTClient_connectOptions* options); - - -typedef struct MQTTResponse -{ - int version; - enum MQTTReasonCodes reasonCode; - int reasonCodeCount; /* used for subscribeMany5 and unsubscribeMany5 */ - enum MQTTReasonCodes* reasonCodes; /* used for subscribeMany5 and unsubscribeMany5 */ - MQTTProperties* properties; /* optional */ -} MQTTResponse; - -#define MQTTResponse_initializer {1, MQTTREASONCODE_SUCCESS, 0, NULL, NULL} - -DLLExport void MQTTResponse_free(MQTTResponse response); - -DLLExport MQTTResponse MQTTClient_connect5(MQTTClient handle, MQTTClient_connectOptions* options, - MQTTProperties* connectProperties, MQTTProperties* willProperties); - -/** - * This function attempts to disconnect the client from the MQTT - * server. In order to allow the client time to complete handling of messages - * that are in-flight when this function is called, a timeout period is - * specified. When the timeout period has expired, the client disconnects even - * if there are still outstanding message acknowledgements. - * The next time the client connects to the same server, any QoS 1 or 2 - * messages which have not completed will be retried depending on the - * cleansession settings for both the previous and the new connection (see - * MQTTClient_connectOptions.cleansession and MQTTClient_connect()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param timeout The client delays disconnection for up to this time (in - * milliseconds) in order to allow in-flight message transfers to complete. - * @return ::MQTTCLIENT_SUCCESS if the client successfully disconnects from - * the server. An error code is returned if the client was unable to disconnect - * from the server - */ -DLLExport int MQTTClient_disconnect(MQTTClient handle, int timeout); - -DLLExport int MQTTClient_disconnect5(MQTTClient handle, int timeout, enum MQTTReasonCodes reason, MQTTProperties* props); - -/** - * This function allows the client application to test whether or not a - * client is currently connected to the MQTT server. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @return Boolean true if the client is connected, otherwise false. - */ -DLLExport int MQTTClient_isConnected(MQTTClient handle); - - -/* Subscribe is synchronous. QoS list parameter is changed on return to granted QoSs. - Returns return code, MQTTCLIENT_SUCCESS == success, non-zero some sort of error (TBD) */ - -/** - * This function attempts to subscribe a client to a single topic, which may - * contain wildcards (see @ref wildcard). This call also specifies the - * @ref qos requested for the subscription - * (see also MQTTClient_subscribeMany()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param topic The subscription topic, which may include wildcards. - * @param qos The requested quality of service for the subscription. - * @return ::MQTTCLIENT_SUCCESS if the subscription request is successful. - * An error code is returned if there was a problem registering the - * subscription. - */ -DLLExport int MQTTClient_subscribe(MQTTClient handle, const char* topic, int qos); - - -DLLExport MQTTResponse MQTTClient_subscribe5(MQTTClient handle, const char* topic, int qos, - MQTTSubscribe_options* opts, MQTTProperties* props); - -/** - * This function attempts to subscribe a client to a list of topics, which may - * contain wildcards (see @ref wildcard). This call also specifies the - * @ref qos requested for each topic (see also MQTTClient_subscribe()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param count The number of topics for which the client is requesting - * subscriptions. - * @param topic An array (of length count) of pointers to - * topics, each of which may include wildcards. - * @param qos An array (of length count) of @ref qos - * values. qos[n] is the requested QoS for topic[n]. - * @return ::MQTTCLIENT_SUCCESS if the subscription request is successful. - * An error code is returned if there was a problem registering the - * subscriptions. - */ -DLLExport int MQTTClient_subscribeMany(MQTTClient handle, int count, char* const* topic, int* qos); - -DLLExport MQTTResponse MQTTClient_subscribeMany5(MQTTClient handle, int count, char* const* topic, - int* qos, MQTTSubscribe_options* opts, MQTTProperties* props); - -/** - * This function attempts to remove an existing subscription made by the - * specified client. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param topic The topic for the subscription to be removed, which may - * include wildcards (see @ref wildcard). - * @return ::MQTTCLIENT_SUCCESS if the subscription is removed. - * An error code is returned if there was a problem removing the - * subscription. - */ -DLLExport int MQTTClient_unsubscribe(MQTTClient handle, const char* topic); - -DLLExport MQTTResponse MQTTClient_unsubscribe5(MQTTClient handle, const char* topic, MQTTProperties* props); - -/** - * This function attempts to remove existing subscriptions to a list of topics - * made by the specified client. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param count The number subscriptions to be removed. - * @param topic An array (of length count) of pointers to the topics of - * the subscriptions to be removed, each of which may include wildcards. - * @return ::MQTTCLIENT_SUCCESS if the subscriptions are removed. - * An error code is returned if there was a problem removing the subscriptions. - */ -DLLExport int MQTTClient_unsubscribeMany(MQTTClient handle, int count, char* const* topic); - -DLLExport MQTTResponse MQTTClient_unsubscribeMany5(MQTTClient handle, int count, char* const* topic, MQTTProperties* props); - -/** - * This function attempts to publish a message to a given topic (see also - * MQTTClient_publishMessage()). An ::MQTTClient_deliveryToken is issued when - * this function returns successfully. If the client application needs to - * test for succesful delivery of QoS1 and QoS2 messages, this can be done - * either asynchronously or synchronously (see @ref async, - * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param topicName The topic associated with this message. - * @param payloadlen The length of the payload in bytes. - * @param payload A pointer to the byte array payload of the message. - * @param qos The @ref qos of the message. - * @param retained The retained flag for the message. - * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated - * with a token representing the message when the function returns - * successfully. If your application does not use delivery tokens, set this - * argument to NULL. - * @return ::MQTTCLIENT_SUCCESS if the message is accepted for publication. - * An error code is returned if there was a problem accepting the message. - */ -DLLExport int MQTTClient_publish(MQTTClient handle, const char* topicName, int payloadlen, const void* payload, int qos, int retained, - MQTTClient_deliveryToken* dt); - -DLLExport MQTTResponse MQTTClient_publish5(MQTTClient handle, const char* topicName, int payloadlen, const void* payload, - int qos, int retained, MQTTProperties* properties, MQTTClient_deliveryToken* dt); -/** - * This function attempts to publish a message to a given topic (see also - * MQTTClient_publish()). An ::MQTTClient_deliveryToken is issued when - * this function returns successfully. If the client application needs to - * test for succesful delivery of QoS1 and QoS2 messages, this can be done - * either asynchronously or synchronously (see @ref async, - * ::MQTTClient_waitForCompletion and MQTTClient_deliveryComplete()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param topicName The topic associated with this message. - * @param msg A pointer to a valid MQTTClient_message structure containing - * the payload and attributes of the message to be published. - * @param dt A pointer to an ::MQTTClient_deliveryToken. This is populated - * with a token representing the message when the function returns - * successfully. If your application does not use delivery tokens, set this - * argument to NULL. - * @return ::MQTTCLIENT_SUCCESS if the message is accepted for publication. - * An error code is returned if there was a problem accepting the message. - */ -DLLExport int MQTTClient_publishMessage(MQTTClient handle, const char* topicName, MQTTClient_message* msg, MQTTClient_deliveryToken* dt); - - -DLLExport MQTTResponse MQTTClient_publishMessage5(MQTTClient handle, const char* topicName, MQTTClient_message* msg, - MQTTClient_deliveryToken* dt); - -/** - * This function is called by the client application to synchronize execution - * of the main thread with completed publication of a message. When called, - * MQTTClient_waitForCompletion() blocks execution until the message has been - * successful delivered or the specified timeout has expired. See @ref async. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param dt The ::MQTTClient_deliveryToken that represents the message being - * tested for successful delivery. Delivery tokens are issued by the - * publishing functions MQTTClient_publish() and MQTTClient_publishMessage(). - * @param timeout The maximum time to wait in milliseconds. - * @return ::MQTTCLIENT_SUCCESS if the message was successfully delivered. - * An error code is returned if the timeout expires or there was a problem - * checking the token. - */ -DLLExport int MQTTClient_waitForCompletion(MQTTClient handle, MQTTClient_deliveryToken dt, unsigned long timeout); - - -/** - * This function sets a pointer to an array of delivery tokens for - * messages that are currently in-flight (pending completion). - * - * Important note: The memory used to hold the array of tokens is - * malloc()'d in this function. The client application is responsible for - * freeing this memory when it is no longer required. - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param tokens The address of a pointer to an ::MQTTClient_deliveryToken. - * When the function returns successfully, the pointer is set to point to an - * array of tokens representing messages pending completion. The last member of - * the array is set to -1 to indicate there are no more tokens. If no tokens - * are pending, the pointer is set to NULL. - * @return ::MQTTCLIENT_SUCCESS if the function returns successfully. - * An error code is returned if there was a problem obtaining the list of - * pending tokens. - */ -DLLExport int MQTTClient_getPendingDeliveryTokens(MQTTClient handle, MQTTClient_deliveryToken **tokens); - -/** - * When implementing a single-threaded client, call this function periodically - * to allow processing of message retries and to send MQTT keepalive pings. - * If the application is calling MQTTClient_receive() regularly, then it is - * not necessary to call this function. - */ -DLLExport void MQTTClient_yield(void); - -/** - * This function performs a synchronous receive of incoming messages. It should - * be used only when the client application has not set callback methods to - * support asynchronous receipt of messages (see @ref async and - * MQTTClient_setCallbacks()). Using this function allows a single-threaded - * client subscriber application to be written. When called, this function - * blocks until the next message arrives or the specified timeout expires - *(see also MQTTClient_yield()). - * - * Important note: The application must free() the memory allocated - * to the topic and the message when processing is complete (see - * MQTTClient_freeMessage()). - * @param handle A valid client handle from a successful call to - * MQTTClient_create(). - * @param topicName The address of a pointer to a topic. This function - * allocates the memory for the topic and returns it to the application - * by setting topicName to point to the topic. - * @param topicLen The length of the topic. If the return code from this - * function is ::MQTTCLIENT_TOPICNAME_TRUNCATED, the topic contains embedded - * NULL characters and the full topic should be retrieved by using - * topicLen. - * @param message The address of a pointer to the received message. This - * function allocates the memory for the message and returns it to the - * application by setting message to point to the received message. - * The pointer is set to NULL if the timeout expires. - * @param timeout The length of time to wait for a message in milliseconds. - * @return ::MQTTCLIENT_SUCCESS or ::MQTTCLIENT_TOPICNAME_TRUNCATED if a - * message is received. ::MQTTCLIENT_SUCCESS can also indicate that the - * timeout expired, in which case message is NULL. An error code is - * returned if there was a problem trying to receive a message. - */ -DLLExport int MQTTClient_receive(MQTTClient handle, char** topicName, int* topicLen, MQTTClient_message** message, - unsigned long timeout); - -/** - * This function frees memory allocated to an MQTT message, including the - * additional memory allocated to the message payload. The client application - * calls this function when the message has been fully processed. Important - * note: This function does not free the memory allocated to a message - * topic string. It is the responsibility of the client application to free - * this memory using the MQTTClient_free() library function. - * @param msg The address of a pointer to the ::MQTTClient_message structure - * to be freed. - */ -DLLExport void MQTTClient_freeMessage(MQTTClient_message** msg); - -/** - * This function frees memory allocated by the MQTT C client library, especially the - * topic name. This is needed on Windows when the client libary and application - * program have been compiled with different versions of the C compiler. It is - * thus good policy to always use this function when freeing any MQTT C client- - * allocated memory. - * @param ptr The pointer to the client library storage to be freed. - */ -DLLExport void MQTTClient_free(void* ptr); - -/** - * This function frees the memory allocated to an MQTT client (see - * MQTTClient_create()). It should be called when the client is no longer - * required. - * @param handle A pointer to the handle referring to the ::MQTTClient - * structure to be freed. - */ -DLLExport void MQTTClient_destroy(MQTTClient* handle); - - -enum MQTTCLIENT_TRACE_LEVELS -{ - MQTTCLIENT_TRACE_MAXIMUM = 1, - MQTTCLIENT_TRACE_MEDIUM, - MQTTCLIENT_TRACE_MINIMUM, - MQTTCLIENT_TRACE_PROTOCOL, - MQTTCLIENT_TRACE_ERROR, - MQTTCLIENT_TRACE_SEVERE, - MQTTCLIENT_TRACE_FATAL, -}; - - -/** - * This function sets the level of trace information which will be - * returned in the trace callback. - * @param level the trace level required - */ -DLLExport void MQTTClient_setTraceLevel(enum MQTTCLIENT_TRACE_LEVELS level); - - -/** - * This is a callback function prototype which must be implemented if you want - * to receive trace information. - * @param level the trace level of the message returned - * @param message the trace message. This is a pointer to a static buffer which - * will be overwritten on each call. You must copy the data if you want to keep - * it for later. - */ -typedef void MQTTClient_traceCallback(enum MQTTCLIENT_TRACE_LEVELS level, char* message); - -/** - * This function sets the trace callback if needed. If set to NULL, - * no trace information will be returned. The default trace level is - * MQTTASYNC_TRACE_MINIMUM. - * @param callback a pointer to the function which will handle the trace information - */ -DLLExport void MQTTClient_setTraceCallback(MQTTClient_traceCallback* callback); - -/** - * Returns a pointer to the string representation of the error or NULL. - * - * Do not free after use. Returns NULL if the error code is unknown. - */ -DLLExport const char* MQTTClient_strerror(int code); - -#ifdef __cplusplus - } -#endif - -#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 - * calls MQTTClient_setCallbacks(), this puts the client into asynchronous - * mode, otherwise it operates in synchronous mode. - * - * In synchronous mode, the client application runs on a single thread. - * Messages are published using the MQTTClient_publish() and - * MQTTClient_publishMessage() functions. To determine that a QoS1 or QoS2 - * (see @ref qos) message has been successfully delivered, the application - * must call the MQTTClient_waitForCompletion() function. An example showing - * synchronous publication is shown in @ref pubsync. Receiving messages in - * synchronous mode uses the MQTTClient_receive() function. Client applications - * must call either MQTTClient_receive() or MQTTClient_yield() relatively - * frequently in order to allow processing of acknowledgements and the MQTT - * "pings" that keep the network connection to the server alive. - * - * In asynchronous mode, the client application runs on several threads. The - * main program calls functions in the client library to publish and subscribe, - * just as for the synchronous mode. Processing of handshaking and maintaining - * the network connection is performed in the background, however. - * Notifications of status and message reception are provided to the client - * application using callbacks registered with the library by the call to - * MQTTClient_setCallbacks() (see MQTTClient_messageArrived(), - * MQTTClient_connectionLost() and MQTTClient_deliveryComplete()). - * This API is not thread safe however - it is not possible to call it from multiple - * threads without synchronization. You can use the MQTTAsync API for that. - * - * @page wildcard Subscription wildcards - * Every MQTT message includes a topic that classifies it. MQTT servers use - * topics to determine which subscribers should receive messages published to - * the server. - * - * Consider the server receiving messages from several environmental sensors. - * Each sensor publishes its measurement data as a message with an associated - * topic. Subscribing applications need to know which sensor originally - * published each received message. A unique topic is thus used to identify - * each sensor and measurement type. Topics such as SENSOR1TEMP, - * SENSOR1HUMIDITY, SENSOR2TEMP and so on achieve this but are not very - * flexible. If additional sensors are added to the system at a later date, - * subscribing applications must be modified to receive them. - * - * To provide more flexibility, MQTT supports a hierarchical topic namespace. - * This allows application designers to organize topics to simplify their - * management. Levels in the hierarchy are delimited by the '/' character, - * such as SENSOR/1/HUMIDITY. Publishers and subscribers use these - * hierarchical topics as already described. - * - * For subscriptions, two wildcard characters are supported: - *
    - *
  • A '#' character represents a complete sub-tree of the hierarchy and - * thus must be the last character in a subscription topic string, such as - * SENSOR/#. This will match any topic starting with SENSOR/, such as - * SENSOR/1/TEMP and SENSOR/2/HUMIDITY.
  • - *
  • A '+' character represents a single level of the hierarchy and is - * used between delimiters. For example, SENSOR/+/TEMP will match - * SENSOR/1/TEMP and SENSOR/2/TEMP.
  • - *
- * Publishers are not allowed to use the wildcard characters in their topic - * names. - * - * Deciding on your topic hierarchy is an important step in your system design. - * - * @page qos Quality of service - * The MQTT protocol provides three qualities of service for delivering - * messages between clients and servers: "at most once", "at least once" and - * "exactly once". - * - * Quality of service (QoS) is an attribute of an individual message being - * published. An application sets the QoS for a specific message by setting the - * MQTTClient_message.qos field to the required value. - * - * A subscribing client can set the maximum quality of service a server uses - * to send messages that match the client subscriptions. The - * MQTTClient_subscribe() and MQTTClient_subscribeMany() functions set this - * maximum. The QoS of a message forwarded to a subscriber thus might be - * different to the QoS given to the message by the original publisher. - * The lower of the two values is used to forward a message. - * - * The three levels are: - * - * QoS0, At most once: The message is delivered at most once, or it - * may not be delivered at all. Its delivery across the network is not - * acknowledged. The message is not stored. The message could be lost if the - * client is disconnected, or if the server fails. QoS0 is the fastest mode of - * transfer. It is sometimes called "fire and forget". - * - * The MQTT protocol does not require servers to forward publications at QoS0 - * to a client. If the client is disconnected at the time the server receives - * the publication, the publication might be discarded, depending on the - * server implementation. - * - * QoS1, At least once: The message is always delivered at least once. - * It might be delivered multiple times if there is a failure before an - * acknowledgment is received by the sender. The message must be stored - * locally at the sender, until the sender receives confirmation that the - * message has been published by the receiver. The message is stored in case - * the message must be sent again. - * - * QoS2, Exactly once: The message is always delivered exactly once. - * The message must be stored locally at the sender, until the sender receives - * confirmation that the message has been published by the receiver. The - * message is stored in case the message must be sent again. QoS2 is the - * safest, but slowest mode of transfer. A more sophisticated handshaking - * and acknowledgement sequence is used than for QoS1 to ensure no duplication - * of messages occurs. - * @page pubsync Synchronous publication example -@code -#include -#include -#include -#include "MQTTClient.h" - -#define ADDRESS "tcp://localhost:1883" -#define CLIENTID "ExampleClientPub" -#define TOPIC "MQTT Examples" -#define PAYLOAD "Hello World!" -#define QOS 1 -#define TIMEOUT 10000L - -int main(int argc, char* argv[]) -{ - MQTTClient client; - MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - MQTTClient_deliveryToken token; - int rc; - - MQTTClient_create(&client, ADDRESS, CLIENTID, - MQTTCLIENT_PERSISTENCE_NONE, NULL); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - - if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) - { - printf("Failed to connect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - pubmsg.payload = PAYLOAD; - pubmsg.payloadlen = strlen(PAYLOAD); - pubmsg.qos = QOS; - pubmsg.retained = 0; - MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token); - printf("Waiting for up to %d seconds for publication of %s\n" - "on topic %s for client with ClientID: %s\n", - (int)(TIMEOUT/1000), PAYLOAD, TOPIC, CLIENTID); - rc = MQTTClient_waitForCompletion(client, token, TIMEOUT); - printf("Message with delivery token %d delivered\n", token); - MQTTClient_disconnect(client, 10000); - MQTTClient_destroy(&client); - return rc; -} - - * @endcode - * - * @page pubasync Asynchronous publication example -@code{.c} -#include -#include -#include -#include "MQTTClient.h" - -#define ADDRESS "tcp://localhost:1883" -#define CLIENTID "ExampleClientPub" -#define TOPIC "MQTT Examples" -#define PAYLOAD "Hello World!" -#define QOS 1 -#define TIMEOUT 10000L - -volatile MQTTClient_deliveryToken deliveredtoken; - -void delivered(void *context, MQTTClient_deliveryToken dt) -{ - printf("Message with token value %d delivery confirmed\n", dt); - deliveredtoken = dt; -} - -int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) -{ - int i; - char* payloadptr; - - printf("Message arrived\n"); - printf(" topic: %s\n", topicName); - printf(" message: "); - - payloadptr = message->payload; - for(i=0; ipayloadlen; i++) - { - putchar(*payloadptr++); - } - putchar('\n'); - MQTTClient_freeMessage(&message); - MQTTClient_free(topicName); - return 1; -} - -void connlost(void *context, char *cause) -{ - printf("\nConnection lost\n"); - printf(" cause: %s\n", cause); -} - -int main(int argc, char* argv[]) -{ - MQTTClient client; - MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - MQTTClient_deliveryToken token; - int rc; - - MQTTClient_create(&client, ADDRESS, CLIENTID, - MQTTCLIENT_PERSISTENCE_NONE, NULL); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - - MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered); - - if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) - { - printf("Failed to connect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - pubmsg.payload = PAYLOAD; - pubmsg.payloadlen = strlen(PAYLOAD); - pubmsg.qos = QOS; - pubmsg.retained = 0; - deliveredtoken = 0; - MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token); - printf("Waiting for publication of %s\n" - "on topic %s for client with ClientID: %s\n", - PAYLOAD, TOPIC, CLIENTID); - while(deliveredtoken != token); - MQTTClient_disconnect(client, 10000); - MQTTClient_destroy(&client); - return rc; -} - - * @endcode - * @page subasync Asynchronous subscription example -@code -#include -#include -#include -#include "MQTTClient.h" - -#define ADDRESS "tcp://localhost:1883" -#define CLIENTID "ExampleClientSub" -#define TOPIC "MQTT Examples" -#define PAYLOAD "Hello World!" -#define QOS 1 -#define TIMEOUT 10000L - -volatile MQTTClient_deliveryToken deliveredtoken; - -void delivered(void *context, MQTTClient_deliveryToken dt) -{ - printf("Message with token value %d delivery confirmed\n", dt); - deliveredtoken = dt; -} - -int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message) -{ - int i; - char* payloadptr; - - printf("Message arrived\n"); - printf(" topic: %s\n", topicName); - printf(" message: "); - - payloadptr = message->payload; - for(i=0; ipayloadlen; i++) - { - putchar(*payloadptr++); - } - putchar('\n'); - MQTTClient_freeMessage(&message); - MQTTClient_free(topicName); - return 1; -} - -void connlost(void *context, char *cause) -{ - printf("\nConnection lost\n"); - printf(" cause: %s\n", cause); -} - -int main(int argc, char* argv[]) -{ - MQTTClient client; - MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; - int rc; - int ch; - - MQTTClient_create(&client, ADDRESS, CLIENTID, - MQTTCLIENT_PERSISTENCE_NONE, NULL); - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - - MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered); - - if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) - { - printf("Failed to connect, return code %d\n", rc); - exit(EXIT_FAILURE); - } - printf("Subscribing to topic %s\nfor client %s using QoS%d\n\n" - "Press Q to quit\n\n", TOPIC, CLIENTID, QOS); - MQTTClient_subscribe(client, TOPIC, QOS); - - do - { - ch = getchar(); - } while(ch!='Q' && ch != 'q'); - - MQTTClient_disconnect(client, 10000); - MQTTClient_destroy(&client); - return rc; -} - - * @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/communication/pub_gps/include/paho_mqtt_3c/MQTTClientPersistence.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTClientPersistence.h deleted file mode 100644 index 4c9014d..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTClientPersistence.h +++ /dev/null @@ -1,254 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2012 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -/** - * @file - * \brief This structure represents a persistent data store, used to store - * outbound and inbound messages, in order to achieve reliable messaging. - * - * The MQTT Client persists QoS1 and QoS2 messages in order to meet the - * assurances of delivery associated with these @ref qos levels. The messages - * are saved in persistent storage - * The type and context of the persistence implementation are specified when - * the MQTT client is created (see MQTTClient_create()). The default - * persistence type (::MQTTCLIENT_PERSISTENCE_DEFAULT) uses a file system-based - * persistence mechanism. The persistence_context argument passed to - * MQTTClient_create() when using the default peristence is a string - * representing the location of the persistence directory. If the context - * argument is NULL, the working directory will be used. - * - * To use memory-based persistence, an application passes - * ::MQTTCLIENT_PERSISTENCE_NONE as the persistence_type to - * MQTTClient_create(). This can lead to message loss in certain situations, - * but can be appropriate in some cases (see @ref qos). - * - * Client applications can provide their own persistence mechanism by passing - * ::MQTTCLIENT_PERSISTENCE_USER as the persistence_type. To implement a - * custom persistence mechanism, the application must pass an initialized - * ::MQTTClient_persistence structure as the persistence_context - * argument to MQTTClient_create(). - * - * If the functions defined return an ::MQTTCLIENT_PERSISTENCE_ERROR then the - * state of the persisted data should remain as it was prior to the function - * being called. For example, if Persistence_put() returns - * ::MQTTCLIENT_PERSISTENCE_ERROR, then it is assumed tha tthe persistent store - * does not contain the data that was passed to the function. Similarly, if - * Persistence_remove() returns ::MQTTCLIENT_PERSISTENCE_ERROR then it is - * assumed that the data to be removed is still held in the persistent store. - * - * It is up to the persistence implementation to log any error information that - * may be required to diagnose a persistence mechanism failure. - */ - -/* -/// @cond EXCLUDE -*/ -#if !defined(MQTTCLIENTPERSISTENCE_H) -#define MQTTCLIENTPERSISTENCE_H -/* -/// @endcond -*/ - -/** - * This persistence_type value specifies the default file system-based - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_DEFAULT 0 -/** - * This persistence_type value specifies a memory-based - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_NONE 1 -/** - * This persistence_type value specifies an application-specific - * persistence mechanism (see MQTTClient_create()). - */ -#define MQTTCLIENT_PERSISTENCE_USER 2 - -/** - * Application-specific persistence functions must return this error code if - * there is a problem executing the function. - */ -#define MQTTCLIENT_PERSISTENCE_ERROR -2 - -/** - * @brief Initialize the persistent store. - * - * Either open the existing persistent store for this client ID or create a new - * one if one doesn't exist. If the persistent store is already open, return - * without taking any action. - * - * An application can use the same client identifier to connect to many - * different servers. The clientid in conjunction with the - * serverURI uniquely identifies the persistence store required. - * - * @param handle The address of a pointer to a handle for this persistence - * implementation. This function must set handle to a valid reference to the - * persistence following a successful return. - * The handle pointer is passed as an argument to all the other - * persistence functions. It may include the context parameter and/or any other - * data for use by the persistence functions. - * @param clientID The client identifier for which the persistent store should - * be opened. - * @param serverURI The connection string specified when the MQTT client was - * created (see MQTTClient_create()). - * @param context A pointer to any data required to initialize the persistent - * store (see ::MQTTClient_persistence). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_open)(void** handle, const char* clientID, const char* serverURI, void* context); - -/** - * @brief Close the persistent store referred to by the handle. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_close)(void* handle); - -/** - * @brief Put the specified data into the persistent store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string used as the key for the data to be put in the store. The - * key is later used to retrieve data from the store with Persistence_get(). - * @param bufcount The number of buffers to write to the persistence store. - * @param buffers An array of pointers to the data buffers associated with - * this key. - * @param buflens An array of lengths of the data buffers. buflen[n] - * gives the length of buffer[n]. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_put)(void* handle, char* key, int bufcount, char* buffers[], int buflens[]); - -/** - * @brief Retrieve the specified data from the persistent store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string that is the key for the data to be retrieved. This is - * the same key used to save the data to the store with Persistence_put(). - * @param buffer The address of a pointer to a buffer. This function sets the - * pointer to point at the retrieved data, if successful. - * @param buflen The address of an int that is set to the length of - * buffer by this function if successful. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_get)(void* handle, char* key, char** buffer, int* buflen); - -/** - * @brief Remove the data for the specified key from the store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key A string that is the key for the data to be removed from the - * store. This is the same key used to save the data to the store with - * Persistence_put(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_remove)(void* handle, char* key); - -/** - * @brief Returns the keys in this persistent data store. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param keys The address of a pointer to pointers to strings. Assuming - * successful execution, this function allocates memory to hold the returned - * keys (strings used to store the data with Persistence_put()). It also - * allocates memory to hold an array of pointers to these strings. keys - * is set to point to the array of pointers to strings. - * @param nkeys A pointer to the number of keys in this persistent data store. - * This function sets the number of keys, if successful. - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_keys)(void* handle, char*** keys, int* nkeys); - -/** - * @brief Clears the persistence store, so that it no longer contains any - * persisted data. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @return Return 0 if the function completes successfully, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_clear)(void* handle); - -/** - * @brief Returns whether any data has been persisted using the specified key. - * - * @param handle The handle pointer from a successful call to - * Persistence_open(). - * @param key The string to be tested for existence in the store. - * @return Return 0 if the key was found in the store, otherwise return - * ::MQTTCLIENT_PERSISTENCE_ERROR. - */ -typedef int (*Persistence_containskey)(void* handle, char* key); - -/** - * @brief A structure containing the function pointers to a persistence - * implementation and the context or state that will be shared across all - * the persistence functions. - */ -typedef struct { - /** - * A pointer to any data required to initialize the persistent store. - */ - void* context; - /** - * A function pointer to an implementation of Persistence_open(). - */ - Persistence_open popen; - /** - * A function pointer to an implementation of Persistence_close(). - */ - Persistence_close pclose; - /** - * A function pointer to an implementation of Persistence_put(). - */ - Persistence_put pput; - /** - * A function pointer to an implementation of Persistence_get(). - */ - Persistence_get pget; - /** - * A function pointer to an implementation of Persistence_remove(). - */ - Persistence_remove premove; - /** - * A function pointer to an implementation of Persistence_keys(). - */ - Persistence_keys pkeys; - /** - * A function pointer to an implementation of Persistence_clear(). - */ - Persistence_clear pclear; - /** - * A function pointer to an implementation of Persistence_containskey(). - */ - Persistence_containskey pcontainskey; -} MQTTClient_persistence; - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTConnect.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTConnect.h deleted file mode 100644 index 98c2c16..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTConnect.h +++ /dev/null @@ -1,148 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014, 2017 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - add connack return code definitions - * Xiang Rong - 442039 Add makefile to Embedded C client - * Ian Craggs - fix for issue #64, bit order in connack response - *******************************************************************************/ - -#ifndef MQTTCONNECT_H_ -#define MQTTCONNECT_H_ - -enum connack_return_codes -{ - MQTT_CONNECTION_ACCEPTED = 0, - MQTT_UNNACCEPTABLE_PROTOCOL = 1, - MQTT_CLIENTID_REJECTED = 2, - MQTT_SERVER_UNAVAILABLE = 3, - MQTT_BAD_USERNAME_OR_PASSWORD = 4, - MQTT_NOT_AUTHORIZED = 5, -}; - -#if !defined(DLLImport) - #define DLLImport -#endif -#if !defined(DLLExport) - #define DLLExport -#endif - - -typedef union -{ - unsigned char all; /**< all connect flags */ -#if defined(REVERSED) - struct - { - unsigned int username : 1; /**< 3.1 user name */ - unsigned int password : 1; /**< 3.1 password */ - unsigned int willRetain : 1; /**< will retain setting */ - unsigned int willQoS : 2; /**< will QoS value */ - unsigned int will : 1; /**< will flag */ - unsigned int cleansession : 1; /**< clean session flag */ - unsigned int : 1; /**< unused */ - } bits; -#else - struct - { - unsigned int : 1; /**< unused */ - unsigned int cleansession : 1; /**< cleansession flag */ - unsigned int will : 1; /**< will flag */ - unsigned int willQoS : 2; /**< will QoS value */ - unsigned int willRetain : 1; /**< will retain setting */ - unsigned int password : 1; /**< 3.1 password */ - unsigned int username : 1; /**< 3.1 user name */ - } bits; -#endif -} MQTTConnectFlags; /**< connect flags byte */ - - - -/** - * Defines the MQTT "Last Will and Testament" (LWT) settings for - * the connect packet. - */ -typedef struct -{ - /** The eyecatcher for this structure. must be MQTW. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 */ - int struct_version; - /** The LWT topic to which the LWT message will be published. */ - MQTTString topicName; - /** The LWT payload. */ - MQTTString message; - /** - * The retained flag for the LWT message (see MQTTAsync_message.retained). - */ - unsigned char retained; - /** - * The quality of service setting for the LWT message (see - * MQTTAsync_message.qos and @ref qos). - */ - char qos; -} MQTTPacket_willOptions; - - -#define MQTTPacket_willOptions_initializer { {'M', 'Q', 'T', 'W'}, 0, {NULL, {0, NULL}}, {NULL, {0, NULL}}, 0, 0 } - - -typedef struct -{ - /** The eyecatcher for this structure. must be MQTC. */ - char struct_id[4]; - /** The version number of this structure. Must be 0 */ - int struct_version; - /** Version of MQTT to be used. 3 = 3.1 4 = 3.1.1 - */ - unsigned char MQTTVersion; - MQTTString clientID; - unsigned short keepAliveInterval; - unsigned char cleansession; - unsigned char willFlag; - MQTTPacket_willOptions will; - MQTTString username; - MQTTString password; -} MQTTPacket_connectData; - -typedef union -{ - unsigned char all; /**< all connack flags */ -#if defined(REVERSED) - struct - { - unsigned int reserved : 7; /**< unused */ - unsigned int sessionpresent : 1; /**< session present flag */ - } bits; -#else - struct - { - unsigned int sessionpresent : 1; /**< session present flag */ - unsigned int reserved: 7; /**< unused */ - } bits; -#endif -} MQTTConnackFlags; /**< connack flags byte */ - -#define MQTTPacket_connectData_initializer { {'M', 'Q', 'T', 'C'}, 0, 4, {NULL, {0, NULL}}, 60, 1, 0, \ - MQTTPacket_willOptions_initializer, {NULL, {0, NULL}}, {NULL, {0, NULL}} } - -DLLExport int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options); -DLLExport int MQTTDeserialize_connect(MQTTPacket_connectData* data, unsigned char* buf, int len); - -DLLExport int MQTTSerialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, unsigned char sessionPresent); -DLLExport int MQTTDeserialize_connack(unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen); - -DLLExport int MQTTSerialize_disconnect(unsigned char* buf, int buflen); -DLLExport int MQTTSerialize_pingreq(unsigned char* buf, int buflen); - -#endif /* MQTTCONNECT_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTFormat.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTFormat.h deleted file mode 100644 index 47b0c41..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTFormat.h +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(MQTTFORMAT_H) -#define MQTTFORMAT_H - -#include "StackTrace.h" -#include "MQTTPacket.h" - -const char* MQTTPacket_getName(unsigned short packetid); -int MQTTStringFormat_connect(char* strbuf, int strbuflen, MQTTPacket_connectData* data); -int MQTTStringFormat_connack(char* strbuf, int strbuflen, unsigned char connack_rc, unsigned char sessionPresent); -int MQTTStringFormat_publish(char* strbuf, int strbuflen, unsigned char dup, int qos, unsigned char retained, - unsigned short packetid, MQTTString topicName, unsigned char* payload, int payloadlen); -int MQTTStringFormat_ack(char* strbuf, int strbuflen, unsigned char packettype, unsigned char dup, unsigned short packetid); -int MQTTStringFormat_subscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, int count, - MQTTString topicFilters[], int requestedQoSs[]); -int MQTTStringFormat_suback(char* strbuf, int strbuflen, unsigned short packetid, int count, int* grantedQoSs); -int MQTTStringFormat_unsubscribe(char* strbuf, int strbuflen, unsigned char dup, unsigned short packetid, - int count, MQTTString topicFilters[]); -char* MQTTFormat_toClientString(char* strbuf, int strbuflen, unsigned char* buf, int buflen); -char* MQTTFormat_toServerString(char* strbuf, int strbuflen, unsigned char* buf, int buflen); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacket.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacket.h deleted file mode 100644 index 350886e..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacket.h +++ /dev/null @@ -1,270 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - * Ian Craggs - MQTT 3.1.1 support - * Ian Craggs - big endian Linux reversed definition - * Ian Craggs - MQTT 5.0 support - *******************************************************************************/ - -#if !defined(MQTTPACKET_H) -#define MQTTPACKET_H - -#include "Socket.h" -#if defined(OPENSSL) -#include "SSLSocket.h" -#endif -#include "LinkedList.h" -#include "Clients.h" - -typedef unsigned int bool; -typedef void* (*pf)(int, unsigned char, char*, size_t); - -#include "MQTTProperties.h" -#include "MQTTReasonCodes.h" - -enum errors -{ - MQTTPACKET_BAD = -4, - MQTTPACKET_BUFFER_TOO_SHORT = -2, - MQTTPACKET_READ_ERROR = -1, - MQTTPACKET_READ_COMPLETE -}; - - -enum msgTypes -{ - CONNECT = 1, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, - PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, - PINGREQ, PINGRESP, DISCONNECT, AUTH -}; - -#if defined(__linux__) -#include -#if __BYTE_ORDER == __BIG_ENDIAN - #define REVERSED 1 -#endif -#endif - -/** - * Bitfields for the MQTT header byte. - */ -typedef union -{ - /*unsigned*/ char byte; /**< the whole byte */ -#if defined(REVERSED) - struct - { - unsigned int type : 4; /**< message type nibble */ - bool dup : 1; /**< DUP flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - bool retain : 1; /**< retained flag bit */ - } bits; -#else - struct - { - bool retain : 1; /**< retained flag bit */ - unsigned int qos : 2; /**< QoS value, 0, 1 or 2 */ - bool dup : 1; /**< DUP flag bit */ - unsigned int type : 4; /**< message type nibble */ - } bits; -#endif -} Header; - - -/** - * Data for a connect packet. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - union - { - unsigned char all; /**< all connect flags */ -#if defined(REVERSED) - struct - { - bool username : 1; /**< 3.1 user name */ - bool password : 1; /**< 3.1 password */ - bool willRetain : 1; /**< will retain setting */ - unsigned int willQoS : 2; /**< will QoS value */ - bool will : 1; /**< will flag */ - bool cleanstart : 1; /**< cleansession flag */ - int : 1; /**< unused */ - } bits; -#else - struct - { - int : 1; /**< unused */ - bool cleanstart : 1; /**< cleansession flag */ - bool will : 1; /**< will flag */ - unsigned int willQoS : 2; /**< will QoS value */ - bool willRetain : 1; /**< will retain setting */ - bool password : 1; /**< 3.1 password */ - bool username : 1; /**< 3.1 user name */ - } bits; -#endif - } flags; /**< connect flags byte */ - - char *Protocol, /**< MQTT protocol name */ - *clientID, /**< string client id */ - *willTopic, /**< will topic */ - *willMsg; /**< will payload */ - - int keepAliveTimer; /**< keepalive timeout value in seconds */ - unsigned char version; /**< MQTT version number */ -} Connect; - - -/** - * Data for a connack packet. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - union - { - unsigned char all; /**< all connack flags */ -#if defined(REVERSED) - struct - { - unsigned int reserved : 7; /**< message type nibble */ - bool sessionPresent : 1; /**< was a session found on the server? */ - } bits; -#else - struct - { - bool sessionPresent : 1; /**< was a session found on the server? */ - unsigned int reserved : 7; /**< message type nibble */ - } bits; -#endif - } flags; /**< connack flags byte */ - unsigned char rc; /**< connack reason code */ - unsigned int MQTTVersion; /**< the version of MQTT */ - MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */ -} Connack; - - -/** - * Data for a packet with header only. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ -} MQTTPacket; - - -/** - * Data for a suback packet. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - int msgId; /**< MQTT message id */ - int MQTTVersion; /**< the version of MQTT */ - MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */ - List* qoss; /**< list of granted QoSs (MQTT 3/4) / reason codes (MQTT 5) */ -} Suback; - - -/** - * Data for an MQTT V5 unsuback packet. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - int msgId; /**< MQTT message id */ - int MQTTVersion; /**< the version of MQTT */ - MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */ - List* reasonCodes; /**< list of reason codes */ -} Unsuback; - - -/** - * Data for a publish packet. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - char* topic; /**< topic string */ - int topiclen; - int msgId; /**< MQTT message id */ - char* payload; /**< binary payload, length delimited */ - int payloadlen; /**< payload length */ - int MQTTVersion; /**< the version of MQTT */ - MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */ -} Publish; - - -/** - * Data for one of the ack packets. - */ -typedef struct -{ - Header header; /**< MQTT header byte */ - int msgId; /**< MQTT message id */ - unsigned char rc; /**< MQTT 5 reason code */ - int MQTTVersion; /**< the version of MQTT */ - MQTTProperties properties; /**< MQTT 5.0 properties. Not used for MQTT < 5.0 */ -} Ack; - -typedef Ack Puback; -typedef Ack Pubrec; -typedef Ack Pubrel; -typedef Ack Pubcomp; - -int MQTTPacket_encode(char* buf, size_t length); -int MQTTPacket_decode(networkHandles* net, size_t* value); -int readInt(char** pptr); -char* readUTF(char** pptr, char* enddata); -unsigned char readChar(char** pptr); -void writeChar(char** pptr, char c); -void writeInt(char** pptr, int anInt); -void writeUTF(char** pptr, const char* string); -void writeData(char** pptr, const void* data, int datalen); - -const char* MQTTPacket_name(int ptype); - -void* MQTTPacket_Factory(int MQTTVersion, networkHandles* net, int* error); -int MQTTPacket_send(networkHandles* net, Header header, char* buffer, size_t buflen, int free, int MQTTVersion); -int MQTTPacket_sends(networkHandles* net, Header header, int count, char** buffers, size_t* buflens, int* frees, int MQTTVersion); - -void* MQTTPacket_header_only(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); -int MQTTPacket_send_disconnect(Clients* client, enum MQTTReasonCodes reason, MQTTProperties* props); - -void* MQTTPacket_publish(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); -void MQTTPacket_freePublish(Publish* pack); -int MQTTPacket_send_publish(Publish* pack, int dup, int qos, int retained, networkHandles* net, const char* clientID); -int MQTTPacket_send_puback(int msgid, networkHandles* net, const char* clientID); -void* MQTTPacket_ack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); - -void MQTTPacket_freeAck(Ack* pack); -void MQTTPacket_freeSuback(Suback* pack); -void MQTTPacket_freeUnsuback(Unsuback* pack); -int MQTTPacket_send_pubrec(int msgid, networkHandles* net, const char* clientID); -int MQTTPacket_send_pubrel(int msgid, int dup, networkHandles* net, const char* clientID); -int MQTTPacket_send_pubcomp(int msgid, networkHandles* net, const char* clientID); - -void MQTTPacket_free_packet(MQTTPacket* pack); - -void writeInt4(char** pptr, int anInt); -int readInt4(char** pptr); -void writeMQTTLenString(char** pptr, MQTTLenString lenstring); -int MQTTLenStringRead(MQTTLenString* lenstring, char** pptr, char* enddata); -int MQTTPacket_VBIlen(int rem_len); -int MQTTPacket_decodeBuf(char* buf, int* value); - -#include "MQTTPacketOut.h" - -#endif /* MQTTPACKET_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacketOut.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacketOut.h deleted file mode 100644 index 4e0ae10..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPacketOut.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - * Ian Craggs - MQTT 3.1.1 support - * Ian Craggs - MQTT 5.0 support - *******************************************************************************/ - -#if !defined(MQTTPACKETOUT_H) -#define MQTTPACKETOUT_H - -#include "MQTTPacket.h" - -int MQTTPacket_send_connect(Clients* client, int MQTTVersion, - MQTTProperties* connectProperties, MQTTProperties* willProperties); -void* MQTTPacket_connack(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); -void MQTTPacket_freeConnack(Connack* pack); - -int MQTTPacket_send_pingreq(networkHandles* net, const char* clientID); - -int MQTTPacket_send_subscribe(List* topics, List* qoss, MQTTSubscribe_options* opts, MQTTProperties* props, - int msgid, int dup, Clients* client); -void* MQTTPacket_suback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); - -int MQTTPacket_send_unsubscribe(List* topics, MQTTProperties* props, int msgid, int dup, Clients* client); -void* MQTTPacket_unsuback(int MQTTVersion, unsigned char aHeader, char* data, size_t datalen); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistence.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistence.h deleted file mode 100644 index 93edb2b..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistence.h +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - async client updates - * Ian Craggs - fix for bug 432903 - queue persistence - * Ian Craggs - MQTT V5 updates - *******************************************************************************/ - -#if !defined(MQTTPERSISTENCE_H) -#define MQTTPERSISTENCE_H - -#if defined(__cplusplus) - extern "C" { -#endif - -#include "Clients.h" -#include "MQTTProperties.h" - -/** Stem of the key for a sent PUBLISH QoS1 or QoS2 */ -#define PERSISTENCE_PUBLISH_SENT "s-" -/** Stem of the key for a sent PUBREL */ -#define PERSISTENCE_PUBREL "sc-" -/** Stem of the key for a received PUBLISH QoS2 */ -#define PERSISTENCE_PUBLISH_RECEIVED "r-" - -/** Stem of the key for a sent MQTT V5 PUBLISH QoS1 or QoS2 */ -#define PERSISTENCE_V5_PUBLISH_SENT "s5-" -/** Stem of the key for a sent MQTT V5 PUBREL */ -#define PERSISTENCE_V5_PUBREL "sc5-" -/** Stem of the key for a received MQTT V5 PUBLISH QoS2 */ -#define PERSISTENCE_V5_PUBLISH_RECEIVED "r5-" - -/** Stem of the key for an async client command */ -#define PERSISTENCE_COMMAND_KEY "c-" -/** Stem of the key for an MQTT V5 async client command */ -#define PERSISTENCE_V5_COMMAND_KEY "c-" -/** Stem of the key for an async client message queue */ -#define PERSISTENCE_QUEUE_KEY "q-" -/** Stem of the key for an MQTT V5 message queue */ -#define PERSISTENCE_V5_QUEUE_KEY "q5-" -#define PERSISTENCE_MAX_KEY_LENGTH 8 - -int MQTTPersistence_create(MQTTClient_persistence** per, int type, void* pcontext); -int MQTTPersistence_initialize(Clients* c, const char* serverURI); -int MQTTPersistence_close(Clients* c); -int MQTTPersistence_clear(Clients* c); -int MQTTPersistence_restore(Clients* c); -void* MQTTPersistence_restorePacket(int MQTTVersion, char* buffer, size_t buflen); -void MQTTPersistence_insertInOrder(List* list, void* content, size_t size); -int MQTTPersistence_put(int socket, char* buf0, size_t buf0len, int count, - char** buffers, size_t* buflens, int htype, int msgId, int scr, int MQTTVersion); -int MQTTPersistence_remove(Clients* c, char* type, int qos, int msgId); -void MQTTPersistence_wrapMsgID(Clients *c); - -typedef struct -{ - char struct_id[4]; - int struct_version; - int payloadlen; - void* payload; - int qos; - int retained; - int dup; - int msgid; - MQTTProperties properties; -} MQTTPersistence_message; - -typedef struct -{ - MQTTPersistence_message* msg; - char* topicName; - int topicLen; - unsigned int seqno; /* only used on restore */ -} MQTTPersistence_qEntry; - -int MQTTPersistence_unpersistQueueEntry(Clients* client, MQTTPersistence_qEntry* qe); -int MQTTPersistence_persistQueueEntry(Clients* aclient, MQTTPersistence_qEntry* qe); -int MQTTPersistence_restoreMessageQueue(Clients* c); -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistenceDefault.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistenceDefault.h deleted file mode 100644 index 9c1034c..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPersistenceDefault.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(MQTTPERSISTENCEDEFAULT_H) -#define MQTTPERSISTENCEDEFAULT_H - -/** 8.3 filesystem */ -#define MESSAGE_FILENAME_LENGTH 8 -/** Extension of the filename */ -#define MESSAGE_FILENAME_EXTENSION ".msg" - -/* prototypes of the functions for the default file system persistence */ -int pstopen(void** handle, const char* clientID, const char* serverURI, void* context); -int pstclose(void* handle); -int pstput(void* handle, char* key, int bufcount, char* buffers[], int buflens[]); -int pstget(void* handle, char* key, char** buffer, int* buflen); -int pstremove(void* handle, char* key); -int pstkeys(void* handle, char*** keys, int* nkeys); -int pstclear(void* handle); -int pstcontainskey(void* handle, char* key); - -int pstmkdir(char *pPathname); - -#endif - diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProperties.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProperties.h deleted file mode 100644 index deec124..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProperties.h +++ /dev/null @@ -1,225 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(MQTTPROPERTIES_H) -#define MQTTPROPERTIES_H - -#define MQTT_INVALID_PROPERTY_ID -2 - -/** The one byte MQTT V5 property indicator */ -enum MQTTPropertyCodes { - MQTTPROPERTY_CODE_PAYLOAD_FORMAT_INDICATOR = 1, /**< The value is 1 */ - MQTTPROPERTY_CODE_MESSAGE_EXPIRY_INTERVAL = 2, /**< The value is 2 */ - MQTTPROPERTY_CODE_CONTENT_TYPE = 3, /**< The value is 3 */ - MQTTPROPERTY_CODE_RESPONSE_TOPIC = 8, /**< The value is 8 */ - MQTTPROPERTY_CODE_CORRELATION_DATA = 9, /**< The value is 9 */ - MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIER = 11, /**< The value is 11 */ - MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL = 17, /**< The value is 17 */ - MQTTPROPERTY_CODE_ASSIGNED_CLIENT_IDENTIFER = 18,/**< The value is 18 */ - MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE = 19, /**< The value is 19 */ - MQTTPROPERTY_CODE_AUTHENTICATION_METHOD = 21, /**< The value is 21 */ - MQTTPROPERTY_CODE_AUTHENTICATION_DATA = 22, /**< The value is 22 */ - MQTTPROPERTY_CODE_REQUEST_PROBLEM_INFORMATION = 23,/**< The value is 23 */ - MQTTPROPERTY_CODE_WILL_DELAY_INTERVAL = 24, /**< The value is 24 */ - MQTTPROPERTY_CODE_REQUEST_RESPONSE_INFORMATION = 25,/**< The value is 25 */ - MQTTPROPERTY_CODE_RESPONSE_INFORMATION = 26, /**< The value is 26 */ - MQTTPROPERTY_CODE_SERVER_REFERENCE = 28, /**< The value is 28 */ - MQTTPROPERTY_CODE_REASON_STRING = 31, /**< The value is 31 */ - MQTTPROPERTY_CODE_RECEIVE_MAXIMUM = 33, /**< The value is 33*/ - MQTTPROPERTY_CODE_TOPIC_ALIAS_MAXIMUM = 34, /**< The value is 34 */ - MQTTPROPERTY_CODE_TOPIC_ALIAS = 35, /**< The value is 35 */ - MQTTPROPERTY_CODE_MAXIMUM_QOS = 36, /**< The value is 36 */ - MQTTPROPERTY_CODE_RETAIN_AVAILABLE = 37, /**< The value is 37 */ - MQTTPROPERTY_CODE_USER_PROPERTY = 38, /**< The value is 38 */ - MQTTPROPERTY_CODE_MAXIMUM_PACKET_SIZE = 39, /**< The value is 39 */ - MQTTPROPERTY_CODE_WILDCARD_SUBSCRIPTION_AVAILABLE = 40,/**< The value is 40 */ - MQTTPROPERTY_CODE_SUBSCRIPTION_IDENTIFIERS_AVAILABLE = 41,/**< The value is 41 */ - MQTTPROPERTY_CODE_SHARED_SUBSCRIPTION_AVAILABLE = 42/**< The value is 241 */ -}; - -#if defined(WIN32) || defined(WIN64) - #define DLLImport __declspec(dllimport) - #define DLLExport __declspec(dllexport) -#else - #define DLLImport extern - #define DLLExport __attribute__ ((visibility ("default"))) -#endif - -/** - * Returns a printable string description of an MQTT V5 property code. - * @param value an MQTT V5 property code. - * @return the printable string description of the input property code. - * NULL if the code was not found. - */ -DLLExport const char* MQTTPropertyName(enum MQTTPropertyCodes value); - -/** The one byte MQTT V5 property type */ -enum MQTTPropertyTypes { - MQTTPROPERTY_TYPE_BYTE, - MQTTPROPERTY_TYPE_TWO_BYTE_INTEGER, - MQTTPROPERTY_TYPE_FOUR_BYTE_INTEGER, - MQTTPROPERTY_TYPE_VARIABLE_BYTE_INTEGER, - MQTTPROPERTY_TYPE_BINARY_DATA, - MQTTPROPERTY_TYPE_UTF_8_ENCODED_STRING, - MQTTPROPERTY_TYPE_UTF_8_STRING_PAIR -}; - -/** - * Returns the MQTT V5 type code of an MQTT V5 property. - * @param value an MQTT V5 property code. - * @return the MQTT V5 type code of the input property. -1 if the code was not found. - */ -DLLExport int MQTTProperty_getType(enum MQTTPropertyCodes value); - -/** - * The data for a length delimited string - */ -typedef struct -{ - int len; /**< the length of the string */ - char* data; /**< pointer to the string data */ -} MQTTLenString; - - -/** - * Structure to hold an MQTT version 5 property of any type - */ -typedef struct -{ - enum MQTTPropertyCodes identifier; /**< The MQTT V5 property id. A multi-byte integer. */ - /** The value of the property, as a union of the different possible types. */ - union { - char byte; /**< holds the value of a byte property type */ - short integer2; /**< holds the value of a 2 byte integer property type */ - int integer4; /**< holds the value of a 4 byte integer property type */ - struct { - MQTTLenString data; /**< The value of a string property, or the name of a user property. */ - MQTTLenString value; /**< The value of a user property. */ - }; - } value; -} MQTTProperty; - -/** - * MQTT version 5 property list - */ -typedef struct MQTTProperties -{ - int count; /**< number of property entries in the array */ - int max_count; /**< max number of properties that the currently allocated array can store */ - int length; /**< mbi: byte length of all properties */ - MQTTProperty *array; /**< array of properties */ -} MQTTProperties; - -#define MQTTProperties_initializer {0, 0, 0, NULL} - -/** - * Returns the length of the properties structure when serialized ready for network transmission. - * @param props an MQTT V5 property structure. - * @return the length in bytes of the properties when serialized. - */ -int MQTTProperties_len(MQTTProperties* props); - -/** - * Add a property pointer to the property array. There is no memory allocation. - * @param props The property list to add the property to. - * @param prop The property to add to the list. - * @return 0 on success, -1 on failure. - */ -DLLExport int MQTTProperties_add(MQTTProperties* props, const MQTTProperty* prop); - -/** - * Serialize the given property list to a character buffer, e.g. for writing to the network. - * @param pptr pointer to the buffer - move the pointer as we add data - * @param properties pointer to the property list, can be NULL - * @return whether the write succeeded or not: number of bytes written, or < 0 on failure. - */ -int MQTTProperties_write(char** pptr, const MQTTProperties* properties); - -/** - * Reads a property list from a character buffer into an array. - * @param properties pointer to the property list to be filled. Should be initalized but empty. - * @param pptr pointer to the character buffer. - * @param enddata pointer to the end of the character buffer so we don't read beyond. - * @return 1 if the properties were read successfully. - */ -int MQTTProperties_read(MQTTProperties* properties, char** pptr, char* enddata); - -/** - * Free all memory allocated to the property list, including any to individual properties. - * @param properties pointer to the property list. - */ -DLLExport void MQTTProperties_free(MQTTProperties* properties); - -/** - * Copy the contents of a property list, allocating additional memory if needed. - * @param props pointer to the property list. - * @return the duplicated property list. - */ -DLLExport MQTTProperties MQTTProperties_copy(const MQTTProperties* props); - -/** - * Checks if property list contains a specific property. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @return 1 if found, 0 if not. - */ -DLLExport int MQTTProperties_hasProperty(MQTTProperties *props, enum MQTTPropertyCodes propid); - -/** - * Returns the number of instances of a property id. Most properties can exist only once. - * User properties and subscription ids can exist more than once. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @return the number of times found. Can be 0. - */ -DLLExport int MQTTProperties_propertyCount(MQTTProperties *props, enum MQTTPropertyCodes propid); - -/** - * Returns the integer value of a specific property. The property given must be a numeric type. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @return the integer value of the property. -9999999 on failure. - */ -DLLExport int MQTTProperties_getNumericValue(MQTTProperties *props, enum MQTTPropertyCodes propid); - -/** - * Returns the integer value of a specific property when it's not the only instance. - * The property given must be a numeric type. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @param index the instance number, starting at 0. - * @return the integer value of the property. -9999999 on failure. - */ -DLLExport int MQTTProperties_getNumericValueAt(MQTTProperties *props, enum MQTTPropertyCodes propid, int index); - -/** - * Returns a pointer to the property structure for a specific property. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @return the pointer to the property structure if found. NULL if not found. - */ -DLLExport MQTTProperty* MQTTProperties_getProperty(MQTTProperties *props, enum MQTTPropertyCodes propid); - -/** - * Returns a pointer to the property structure for a specific property when it's not the only instance. - * @param props pointer to the property list. - * @param propid the property id to check for. - * @param index the instance number, starting at 0. - * @return the pointer to the property structure if found. NULL if not found. - */ -DLLExport MQTTProperty* MQTTProperties_getPropertyAt(MQTTProperties *props, enum MQTTPropertyCodes propid, int index); - -#endif /* MQTTPROPERTIES_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocol.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocol.h deleted file mode 100644 index 7478103..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocol.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs - MQTT 3.1.1 updates - *******************************************************************************/ - -#if !defined(MQTTPROTOCOL_H) -#define MQTTPROTOCOL_H - -#include "LinkedList.h" -#include "MQTTPacket.h" -#include "Clients.h" - -#define MAX_MSG_ID 65535 -#define MAX_CLIENTID_LEN 65535 - -typedef struct -{ - int socket; - Publications* p; -} pending_write; - - -typedef struct -{ - List publications; - unsigned int msgs_received; - unsigned int msgs_sent; - List pending_writes; /* for qos 0 writes not complete */ -} MQTTProtocol; - - -#include "MQTTProtocolOut.h" - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolClient.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolClient.h deleted file mode 100644 index 92b43a8..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolClient.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2017 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - * Ian Craggs - MQTT 3.1.1 updates - * Rong Xiang, Ian Craggs - C++ compatibility - * Ian Craggs - add debug definition of MQTTStrdup for when needed - *******************************************************************************/ - -#if !defined(MQTTPROTOCOLCLIENT_H) -#define MQTTPROTOCOLCLIENT_H - -#include "LinkedList.h" -#include "MQTTPacket.h" -#include "Log.h" -#include "MQTTProtocol.h" -#include "Messages.h" -#include "MQTTProperties.h" - -#define MAX_MSG_ID 65535 -#define MAX_CLIENTID_LEN 65535 - -int MQTTProtocol_startPublish(Clients* pubclient, Publish* publish, int qos, int retained, Messages** m); -Messages* MQTTProtocol_createMessage(Publish* publish, Messages** mm, int qos, int retained); -Publications* MQTTProtocol_storePublication(Publish* publish, int* len); -int messageIDCompare(void* a, void* b); -int MQTTProtocol_assignMsgId(Clients* client); -void MQTTProtocol_removePublication(Publications* p); -void Protocol_processPublication(Publish* publish, Clients* client); - -int MQTTProtocol_handlePublishes(void* pack, int sock); -int MQTTProtocol_handlePubacks(void* pack, int sock); -int MQTTProtocol_handlePubrecs(void* pack, int sock); -int MQTTProtocol_handlePubrels(void* pack, int sock); -int MQTTProtocol_handlePubcomps(void* pack, int sock); - -void MQTTProtocol_closeSession(Clients* c, int sendwill); -void MQTTProtocol_keepalive(time_t); -void MQTTProtocol_retry(time_t, int, int); -void MQTTProtocol_freeClient(Clients* client); -void MQTTProtocol_emptyMessageList(List* msgList); -void MQTTProtocol_freeMessageList(List* msgList); - -char* MQTTStrncpy(char *dest, const char* src, size_t num); -char* MQTTStrdup(const char* src); - -//#define MQTTStrdup(src) MQTTStrncpy(malloc(strlen(src)+1), src, strlen(src)+1) - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolOut.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolOut.h deleted file mode 100644 index e2c2645..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTProtocolOut.h +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - * Ian Craggs - MQTT 3.1.1 support - * Ian Craggs - SNI support - * Ian Craggs - MQTT 5.0 support - *******************************************************************************/ - -#if !defined(MQTTPROTOCOLOUT_H) -#define MQTTPROTOCOLOUT_H - -#include "LinkedList.h" -#include "MQTTPacket.h" -#include "Clients.h" -#include "Log.h" -#include "Messages.h" -#include "MQTTProtocol.h" -#include "MQTTProtocolClient.h" - -#define DEFAULT_PORT 1883 - -size_t MQTTProtocol_addressPort(const char* uri, int* port, const char **topic); -void MQTTProtocol_reconnect(const char* ip_address, Clients* client); -#if defined(OPENSSL) -int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int ssl, int websocket, int MQTTVersion, - MQTTProperties* connectProperties, MQTTProperties* willProperties); -#else -int MQTTProtocol_connect(const char* ip_address, Clients* acClients, int websocket, int MQTTVersion, - MQTTProperties* connectProperties, MQTTProperties* willProperties); -#endif -int MQTTProtocol_handlePingresps(void* pack, int sock); -int MQTTProtocol_subscribe(Clients* client, List* topics, List* qoss, int msgID, - MQTTSubscribe_options* opts, MQTTProperties* props); -int MQTTProtocol_handleSubacks(void* pack, int sock); -int MQTTProtocol_unsubscribe(Clients* client, List* topics, int msgID, MQTTProperties* props); -int MQTTProtocol_handleUnsubacks(void* pack, int sock); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPublish.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPublish.h deleted file mode 100644 index ebe479d..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTPublish.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#ifndef MQTTPUBLISH_H_ -#define MQTTPUBLISH_H_ - -#if !defined(DLLImport) - #define DLLImport -#endif -#if !defined(DLLExport) - #define DLLExport -#endif - -DLLExport int MQTTSerialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, unsigned short packetid, - MQTTString topicName, unsigned char* payload, int payloadlen); - -DLLExport int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, - unsigned char** payload, int* payloadlen, unsigned char* buf, int len); - -DLLExport int MQTTSerialize_puback(unsigned char* buf, int buflen, unsigned short packetid); -DLLExport int MQTTSerialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid); -DLLExport int MQTTSerialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid); - -#endif /* MQTTPUBLISH_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTReasonCodes.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTReasonCodes.h deleted file mode 100644 index 369543b..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTReasonCodes.h +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2017, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(MQTTREASONCODES_H) -#define MQTTREASONCODES_H - -/** The MQTT V5 one byte reason code */ -enum MQTTReasonCodes { - MQTTREASONCODE_SUCCESS = 0, - MQTTREASONCODE_NORMAL_DISCONNECTION = 0, - MQTTREASONCODE_GRANTED_QOS_0 = 0, - MQTTREASONCODE_GRANTED_QOS_1 = 1, - MQTTREASONCODE_GRANTED_QOS_2 = 2, - MQTTREASONCODE_DISCONNECT_WITH_WILL_MESSAGE = 4, - MQTTREASONCODE_NO_MATCHING_SUBSCRIBERS = 16, - MQTTREASONCODE_NO_SUBSCRIPTION_FOUND = 17, - MQTTREASONCODE_CONTINUE_AUTHENTICATION = 24, - MQTTREASONCODE_RE_AUTHENTICATE = 25, - MQTTREASONCODE_UNSPECIFIED_ERROR = 128, - MQTTREASONCODE_MALFORMED_PACKET = 129, - MQTTREASONCODE_PROTOCOL_ERROR = 130, - MQTTREASONCODE_IMPLEMENTATION_SPECIFIC_ERROR = 131, - MQTTREASONCODE_UNSUPPORTED_PROTOCOL_VERSION = 132, - MQTTREASONCODE_CLIENT_IDENTIFIER_NOT_VALID = 133, - MQTTREASONCODE_BAD_USER_NAME_OR_PASSWORD = 134, - MQTTREASONCODE_NOT_AUTHORIZED = 135, - MQTTREASONCODE_SERVER_UNAVAILABLE = 136, - MQTTREASONCODE_SERVER_BUSY = 137, - MQTTREASONCODE_BANNED = 138, - MQTTREASONCODE_SERVER_SHUTTING_DOWN = 139, - MQTTREASONCODE_BAD_AUTHENTICATION_METHOD = 140, - MQTTREASONCODE_KEEP_ALIVE_TIMEOUT = 141, - MQTTREASONCODE_SESSION_TAKEN_OVER = 142, - MQTTREASONCODE_TOPIC_FILTER_INVALID = 143, - MQTTREASONCODE_TOPIC_NAME_INVALID = 144, - MQTTREASONCODE_PACKET_IDENTIFIER_IN_USE = 145, - MQTTREASONCODE_PACKET_IDENTIFIER_NOT_FOUND = 146, - MQTTREASONCODE_RECEIVE_MAXIMUM_EXCEEDED = 147, - MQTTREASONCODE_TOPIC_ALIAS_INVALID = 148, - MQTTREASONCODE_PACKET_TOO_LARGE = 149, - MQTTREASONCODE_MESSAGE_RATE_TOO_HIGH = 150, - MQTTREASONCODE_QUOTA_EXCEEDED = 151, - MQTTREASONCODE_ADMINISTRATIVE_ACTION = 152, - MQTTREASONCODE_PAYLOAD_FORMAT_INVALID = 153, - MQTTREASONCODE_RETAIN_NOT_SUPPORTED = 154, - MQTTREASONCODE_QOS_NOT_SUPPORTED = 155, - MQTTREASONCODE_USE_ANOTHER_SERVER = 156, - MQTTREASONCODE_SERVER_MOVED = 157, - MQTTREASONCODE_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 158, - MQTTREASONCODE_CONNECTION_RATE_EXCEEDED = 159, - MQTTREASONCODE_MAXIMUM_CONNECT_TIME = 160, - MQTTREASONCODE_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161, - MQTTREASONCODE_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 162 -}; - -#if defined(WIN32) || defined(WIN64) - #define DLLImport __declspec(dllimport) - #define DLLExport __declspec(dllexport) -#else - #define DLLImport extern - #define DLLExport __attribute__ ((visibility ("default"))) -#endif - -/** - * Returns a printable string description of an MQTT V5 reason code. - * @param value an MQTT V5 reason code. - * @return the printable string description of the input reason code. - * NULL if the code was not found. - */ -DLLExport const char* MQTTReasonCode_toString(enum MQTTReasonCodes value); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribe.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribe.h deleted file mode 100644 index aa91826..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribe.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#ifndef MQTTSUBSCRIBE_H_ -#define MQTTSUBSCRIBE_H_ - -#if !defined(DLLImport) - #define DLLImport -#endif -#if !defined(DLLExport) - #define DLLExport -#endif - -DLLExport int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, - int count, MQTTString topicFilters[], int requestedQoSs[]); - -DLLExport int MQTTDeserialize_subscribe(unsigned char* dup, unsigned short* packetid, - int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], unsigned char* buf, int len); - -DLLExport int MQTTSerialize_suback(unsigned char* buf, int buflen, unsigned short packetid, int count, int* grantedQoSs); - -DLLExport int MQTTDeserialize_suback(unsigned short* packetid, int maxcount, int* count, int grantedQoSs[], unsigned char* buf, int len); - - -#endif /* MQTTSUBSCRIBE_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribeOpts.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribeOpts.h deleted file mode 100644 index 1ae4678..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTSubscribeOpts.h +++ /dev/null @@ -1,46 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(SUBOPTS_H) -#define SUBOPTS_H - -/** The MQTT V5 subscribe options, apart from QoS which existed before V5. */ -typedef struct MQTTSubscribe_options -{ - /** The eyecatcher for this structure. Must be MQSO. */ - char struct_id[4]; - /** The version number of this structure. Must be 0. - */ - int struct_version; - /** To not receive our own publications, set to 1. - * 0 is the original MQTT behaviour - all messages matching the subscription are received. - */ - unsigned char noLocal; - /** To keep the retain flag as on the original publish message, set to 1. - * If 0, defaults to the original MQTT behaviour where the retain flag is only set on - * publications sent by a broker if in response to a subscribe request. - */ - unsigned char retainAsPublished; - /** 0 - send retained messages at the time of the subscribe (original MQTT behaviour) - * 1 - send retained messages on subscribe only if the subscription is new - * 2 - do not send retained messages at all - */ - unsigned char retainHandling; -} MQTTSubscribe_options; - -#define MQTTSubscribe_options_initializer { {'M', 'Q', 'S', 'O'}, 0, 0, 0, 0 } - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTUnsubscribe.h b/src/communication/pub_gps/include/paho_mqtt_3c/MQTTUnsubscribe.h deleted file mode 100644 index 355ca9a..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/MQTTUnsubscribe.h +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Xiang Rong - 442039 Add makefile to Embedded C client - *******************************************************************************/ - -#ifndef MQTTUNSUBSCRIBE_H_ -#define MQTTUNSUBSCRIBE_H_ - -#if !defined(DLLImport) - #define DLLImport -#endif -#if !defined(DLLExport) - #define DLLExport -#endif - -DLLExport int MQTTSerialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, - int count, MQTTString topicFilters[]); - -DLLExport int MQTTDeserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, int max_count, int* count, MQTTString topicFilters[], - unsigned char* buf, int len); - -DLLExport int MQTTSerialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid); - -DLLExport int MQTTDeserialize_unsuback(unsigned short* packetid, unsigned char* buf, int len); - -#endif /* MQTTUNSUBSCRIBE_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Messages.h b/src/communication/pub_gps/include/paho_mqtt_3c/Messages.h deleted file mode 100644 index 08f292f..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Messages.h +++ /dev/null @@ -1,24 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(MESSAGES_H) -#define MESSAGES_H - -#include "Log.h" - -const char* Messages_get(int, enum LOG_LEVELS); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/OsWrapper.h b/src/communication/pub_gps/include/paho_mqtt_3c/OsWrapper.h deleted file mode 100644 index f657ab1..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/OsWrapper.h +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2016, 2017 logi.cals GmbH - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Gunter Raidl - timer support for VxWorks - * Rainer Poisel - reusability - *******************************************************************************/ - -#if !defined(OSWRAPPER_H) -#define OSWRAPPER_H - -#if defined(_WRS_KERNEL) -#include - -#define lstat stat - -typedef unsigned long useconds_t; -void usleep(useconds_t useconds); - -#define timersub(a, b, result) \ - do \ - { \ - (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((result)->tv_usec < 0) \ - { \ - --(result)->tv_sec; \ - (result)->tv_usec += 1000000L; \ - } \ - } while (0) -#endif /* defined(_WRS_KERNEL) */ - -#endif /* OSWRAPPER_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/SHA1.h b/src/communication/pub_gps/include/paho_mqtt_3c/SHA1.h deleted file mode 100644 index f8e8abd..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/SHA1.h +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Keith Holman - initial implementation and documentation - *******************************************************************************/ - -#if !defined(SHA1_H) -#define SHA1_H - -#if defined(OPENSSL) -#include - -/** SHA-1 Digest Length */ -#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH - -#else /* if defined(OPENSSL) */ - -#if defined(WIN32) || defined(WIN64) -#include -#include -typedef struct SHA_CTX_S -{ - HCRYPTPROV hProv; - HCRYPTHASH hHash; -} SHA_CTX; -#else /* if defined(WIN32) || defined(WIN64) */ - -#include -typedef struct SHA_CTX_S { - uint32_t h[5]; - union { - uint32_t w[16]; - uint8_t buffer[64]; - }; - unsigned int size; - unsigned int total; -} SHA_CTX; -#endif /* else if defined(WIN32) || defined(WIN64) */ - -#include - -/** SHA-1 Digest Length (number of bytes in SHA1) */ -#define SHA1_DIGEST_LENGTH (160/8) - -/** - * Initializes the SHA1 hashing algorithm - * - * @param[in,out] ctx hashing context structure - * - * @see SHA1_Update - * @see SHA1_Final - */ -int SHA1_Init(SHA_CTX *ctx); - -/** - * Updates a block to the SHA1 hash - * - * @param[in,out] ctx hashing context structure - * @param[in] data block of data to hash - * @param[in] len length of block to hash - * - * @see SHA1_Init - * @see SHA1_Final - */ -int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len); - -/** - * Produce final SHA1 hash - * - * @param[out] md SHA1 hash produced (must be atleast - * @p SHA1_DIGEST_LENGTH in length) - * @param[in,out] ctx hashing context structure - * - * @see SHA1_Init - * @see SHA1_Final - */ -int SHA1_Final(unsigned char *md, SHA_CTX *ctx); - -#endif /* if defined(OPENSSL) */ -#endif /* SHA1_H */ - diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/SSLSocket.h b/src/communication/pub_gps/include/paho_mqtt_3c/SSLSocket.h deleted file mode 100644 index 09547fd..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/SSLSocket.h +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs, Allan Stockdill-Mander - initial implementation - * Ian Craggs - SNI support - * Ian Craggs - post connect checks and CApath - *******************************************************************************/ -#if !defined(SSLSOCKET_H) -#define SSLSOCKET_H - -#if defined(WIN32) || defined(WIN64) - #define ssl_mutex_type HANDLE -#else - #include - #include - #define ssl_mutex_type pthread_mutex_t -#endif - -#include -#include "SocketBuffer.h" -#include "Clients.h" - -#define URI_SSL "ssl://" - -/** if we should handle openssl initialization (bool_value == 1) or depend on it to be initalized externally (bool_value == 0) */ -void SSLSocket_handleOpensslInit(int bool_value); - -int SSLSocket_initialize(void); -void SSLSocket_terminate(void); -int SSLSocket_setSocketForSSL(networkHandles* net, MQTTClient_SSLOptions* opts, const char* hostname, size_t hostname_len); - -int SSLSocket_getch(SSL* ssl, int socket, char* c); -char *SSLSocket_getdata(SSL* ssl, int socket, size_t bytes, size_t* actual_len); - -int SSLSocket_close(networkHandles* net); -int SSLSocket_putdatas(SSL* ssl, int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees); -int SSLSocket_connect(SSL* ssl, int sock, const char* hostname, int verify, int (*cb)(const char *str, size_t len, void *u), void* u); - -int SSLSocket_getPendingRead(void); -int SSLSocket_continueWrite(pending_writes* pw); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Socket.h b/src/communication/pub_gps/include/paho_mqtt_3c/Socket.h deleted file mode 100644 index e042069..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Socket.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial implementation and documentation - * Ian Craggs - async client updates - *******************************************************************************/ - -#if !defined(SOCKET_H) -#define SOCKET_H - -#include - -#if defined(WIN32) || defined(WIN64) -#include -#include -#define MAXHOSTNAMELEN 256 -#if !defined(SSLSOCKET_H) -#undef EAGAIN -#define EAGAIN WSAEWOULDBLOCK -#undef EINTR -#define EINTR WSAEINTR -#undef EINPROGRESS -#define EINPROGRESS WSAEINPROGRESS -#undef EWOULDBLOCK -#define EWOULDBLOCK WSAEWOULDBLOCK -#undef ENOTCONN -#define ENOTCONN WSAENOTCONN -#undef ECONNRESET -#define ECONNRESET WSAECONNRESET -#undef ETIMEDOUT -#define ETIMEDOUT WAIT_TIMEOUT -#endif -#define ioctl ioctlsocket -#define socklen_t int -#else -#define INVALID_SOCKET SOCKET_ERROR -#include -#if !defined(_WRS_KERNEL) -#include -#include -#include -#include -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define ULONG size_t -#endif - -#include "mutex_type.h" /* Needed for mutex_type */ - -/** socket operation completed successfully */ -#define TCPSOCKET_COMPLETE 0 -#if !defined(SOCKET_ERROR) - /** error in socket operation */ - #define SOCKET_ERROR -1 -#endif -/** must be the same as SOCKETBUFFER_INTERRUPTED */ -#define TCPSOCKET_INTERRUPTED -22 -#define SSL_FATAL -3 - -#if !defined(INET6_ADDRSTRLEN) -#define INET6_ADDRSTRLEN 46 /** only needed for gcc/cygwin on windows */ -#endif - - -#if !defined(max) -#define max(A,B) ( (A) > (B) ? (A):(B)) -#endif - -#include "LinkedList.h" - -/*BE -def FD_SET -{ - 128 n8 "data" -} - -def SOCKETS -{ - FD_SET "rset" - FD_SET "rset_saved" - n32 dec "maxfdp1" - n32 ptr INTList "clientsds" - n32 ptr INTItem "cur_clientsds" - n32 ptr INTList "connect_pending" - n32 ptr INTList "write_pending" - FD_SET "pending_wset" -} -BE*/ - - -/** - * Structure to hold all socket data for the module - */ -typedef struct -{ - fd_set rset, /**< socket read set (see select doc) */ - rset_saved; /**< saved socket read set */ - int maxfdp1; /**< max descriptor used +1 (again see select doc) */ - List* clientsds; /**< list of client socket descriptors */ - ListElement* cur_clientsds; /**< current client socket descriptor (iterator) */ - List* connect_pending; /**< list of sockets for which a connect is pending */ - List* write_pending; /**< list of sockets for which a write is pending */ - fd_set pending_wset; /**< socket pending write set for select */ -} Sockets; - - -void Socket_outInitialize(void); -void Socket_outTerminate(void); -int Socket_getReadySocket(int more_work, struct timeval *tp, mutex_type mutex); -int Socket_getch(int socket, char* c); -char *Socket_getdata(int socket, size_t bytes, size_t* actual_len); -int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees); -void Socket_close(int socket); -int Socket_new(const char* addr, size_t addr_len, int port, int* socket); - -int Socket_noPendingWrites(int socket); -char* Socket_getpeer(int sock); - -void Socket_addPendingWrite(int socket); -void Socket_clearPendingWrite(int socket); - -typedef void Socket_writeComplete(int socket, int rc); -void Socket_setWriteCompleteCallback(Socket_writeComplete*); - -#endif /* SOCKET_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/SocketBuffer.h b/src/communication/pub_gps/include/paho_mqtt_3c/SocketBuffer.h deleted file mode 100644 index f7702dc..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/SocketBuffer.h +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2014 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - * Ian Craggs, Allan Stockdill-Mander - SSL updates - *******************************************************************************/ - -#if !defined(SOCKETBUFFER_H) -#define SOCKETBUFFER_H - -#if defined(WIN32) || defined(WIN64) -#include -#else -#include -#endif - -#if defined(OPENSSL) -#include -#endif - -#if defined(WIN32) || defined(WIN64) - typedef WSABUF iobuf; -#else - typedef struct iovec iobuf; -#endif - -typedef struct -{ - int socket; - unsigned int index; - size_t headerlen; - char fixed_header[5]; /**< header plus up to 4 length bytes */ - size_t buflen, /**< total length of the buffer */ - datalen; /**< current length of data in buf */ - char* buf; -} socket_queue; - -typedef struct -{ - int socket, count; - size_t total; -#if defined(OPENSSL) - SSL* ssl; -#endif - size_t bytes; - iobuf iovecs[5]; - int frees[5]; -} pending_writes; - -#define SOCKETBUFFER_COMPLETE 0 -#if !defined(SOCKET_ERROR) - #define SOCKET_ERROR -1 -#endif -#define SOCKETBUFFER_INTERRUPTED -22 /* must be the same value as TCPSOCKET_INTERRUPTED */ - -void SocketBuffer_initialize(void); -void SocketBuffer_terminate(void); -void SocketBuffer_cleanup(int socket); -char* SocketBuffer_getQueuedData(int socket, size_t bytes, size_t* actual_len); -int SocketBuffer_getQueuedChar(int socket, char* c); -void SocketBuffer_interrupted(int socket, size_t actual_len); -char* SocketBuffer_complete(int socket); -void SocketBuffer_queueChar(int socket, char c); - -#if defined(OPENSSL) -void SocketBuffer_pendingWrite(int socket, SSL* ssl, int count, iobuf* iovecs, int* frees, size_t total, size_t bytes); -#else -void SocketBuffer_pendingWrite(int socket, int count, iobuf* iovecs, int* frees, size_t total, size_t bytes); -#endif -pending_writes* SocketBuffer_getWrite(int socket); -int SocketBuffer_writeComplete(int socket); -pending_writes* SocketBuffer_updateWrite(int socket, char* topic, char* payload); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/StackTrace.h b/src/communication/pub_gps/include/paho_mqtt_3c/StackTrace.h deleted file mode 100644 index 21a0a64..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/StackTrace.h +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2017 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#ifndef STACKTRACE_H_ -#define STACKTRACE_H_ - -#include -#include "Log.h" -#include "Thread.h" - -#if defined(NOSTACKTRACE) -#define FUNC_ENTRY -#define FUNC_ENTRY_NOLOG -#define FUNC_ENTRY_MED -#define FUNC_ENTRY_MAX -#define FUNC_EXIT -#define FUNC_EXIT_NOLOG -#define FUNC_EXIT_MED -#define FUNC_EXIT_MAX -#define FUNC_EXIT_RC(x) -#define FUNC_EXIT_MED_RC(x) -#define FUNC_EXIT_MAX_RC(x) -#else -#if defined(WIN32) || defined(WIN64) -#define inline __inline -#define FUNC_ENTRY StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MINIMUM) -#define FUNC_ENTRY_NOLOG StackTrace_entry(__FUNCTION__, __LINE__, -1) -#define FUNC_ENTRY_MED StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MEDIUM) -#define FUNC_ENTRY_MAX StackTrace_entry(__FUNCTION__, __LINE__, TRACE_MAXIMUM) -#define FUNC_EXIT StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MINIMUM) -#define FUNC_EXIT_NOLOG StackTrace_exit(__FUNCTION__, __LINE__, -1) -#define FUNC_EXIT_MED StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MEDIUM) -#define FUNC_EXIT_MAX StackTrace_exit(__FUNCTION__, __LINE__, NULL, TRACE_MAXIMUM) -#define FUNC_EXIT_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MINIMUM) -#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MEDIUM) -#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__FUNCTION__, __LINE__, &x, TRACE_MAXIMUM) -#else -#define FUNC_ENTRY StackTrace_entry(__func__, __LINE__, TRACE_MINIMUM) -#define FUNC_ENTRY_NOLOG StackTrace_entry(__func__, __LINE__, -1) -#define FUNC_ENTRY_MED StackTrace_entry(__func__, __LINE__, TRACE_MEDIUM) -#define FUNC_ENTRY_MAX StackTrace_entry(__func__, __LINE__, TRACE_MAXIMUM) -#define FUNC_EXIT StackTrace_exit(__func__, __LINE__, NULL, TRACE_MINIMUM) -#define FUNC_EXIT_NOLOG StackTrace_exit(__func__, __LINE__, NULL, -1) -#define FUNC_EXIT_MED StackTrace_exit(__func__, __LINE__, NULL, TRACE_MEDIUM) -#define FUNC_EXIT_MAX StackTrace_exit(__func__, __LINE__, NULL, TRACE_MAXIMUM) -#define FUNC_EXIT_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MINIMUM) -#define FUNC_EXIT_MED_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MEDIUM) -#define FUNC_EXIT_MAX_RC(x) StackTrace_exit(__func__, __LINE__, &x, TRACE_MAXIMUM) -#endif -#endif - -void StackTrace_entry(const char* name, int line, enum LOG_LEVELS trace); -void StackTrace_exit(const char* name, int line, void* return_value, enum LOG_LEVELS trace); - -void StackTrace_printStack(FILE* dest); -char* StackTrace_get(thread_id_type, char* buf, int bufsize); - -#endif /* STACKTRACE_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Thread.h b/src/communication/pub_gps/include/paho_mqtt_3c/Thread.h deleted file mode 100644 index 88fd008..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Thread.h +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial implementation - * Ian Craggs, Allan Stockdill-Mander - async client updates - * Ian Craggs - fix for bug #420851 - * Ian Craggs - change MacOS semaphore implementation - *******************************************************************************/ -#include "MQTTClient.h" - -#if !defined(THREAD_H) -#define THREAD_H - -#include "mutex_type.h" /* Needed for mutex_type */ - -#if defined(WIN32) || defined(WIN64) - #include - #define thread_type HANDLE - #define thread_id_type DWORD - #define thread_return_type DWORD - #define thread_fn LPTHREAD_START_ROUTINE - #define cond_type HANDLE - #define sem_type HANDLE - #undef ETIMEDOUT - #define ETIMEDOUT WSAETIMEDOUT -#else - #include - - #define thread_type pthread_t - #define thread_id_type pthread_t - #define thread_return_type void* - typedef thread_return_type (*thread_fn)(void*); - typedef struct { pthread_cond_t cond; pthread_mutex_t mutex; } cond_type_struct; - typedef cond_type_struct *cond_type; - #if defined(OSX) - #include - typedef dispatch_semaphore_t sem_type; - #else - #include - typedef sem_t *sem_type; - #endif - - cond_type Thread_create_cond(void); - int Thread_signal_cond(cond_type); - int Thread_wait_cond(cond_type condvar, int timeout); - int Thread_destroy_cond(cond_type); -#endif - -DLLExport thread_type Thread_start(thread_fn, void*); - -DLLExport mutex_type Thread_create_mutex(); -DLLExport int Thread_lock_mutex(mutex_type); -DLLExport int Thread_unlock_mutex(mutex_type); -void Thread_destroy_mutex(mutex_type); - -DLLExport thread_id_type Thread_getid(); - -sem_type Thread_create_sem(void); -int Thread_wait_sem(sem_type sem, int timeout); -int Thread_check_sem(sem_type sem); -int Thread_post_sem(sem_type sem); -int Thread_destroy_sem(sem_type sem); - - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/Tree.h b/src/communication/pub_gps/include/paho_mqtt_3c/Tree.h deleted file mode 100644 index bbbd014..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/Tree.h +++ /dev/null @@ -1,115 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial implementation and documentation - *******************************************************************************/ - - -#if !defined(TREE_H) -#define TREE_H - -#include /* for size_t definition */ - -/*BE -defm defTree(T) // macro to define a tree - -def T concat Node -{ - n32 ptr T concat Node "parent" - n32 ptr T concat Node "left" - n32 ptr T concat Node "right" - n32 ptr T id2str(T) - n32 suppress "size" -} - - -def T concat Tree -{ - struct - { - n32 ptr T concat Node suppress "root" - n32 ptr DATA suppress "compare" - } - struct - { - n32 ptr T concat Node suppress "root" - n32 ptr DATA suppress "compare" - } - n32 dec "count" - n32 dec suppress "size" -} - -endm - -defTree(INT) -defTree(STRING) -defTree(TMP) - -BE*/ - -/** - * Structure to hold all data for one list element - */ -typedef struct NodeStruct -{ - struct NodeStruct *parent, /**< pointer to parent tree node, in case we need it */ - *child[2]; /**< pointers to child tree nodes 0 = left, 1 = right */ - void* content; /**< pointer to element content */ - size_t size; /**< size of content */ - unsigned int red : 1; -} Node; - - -/** - * Structure to hold all data for one tree - */ -typedef struct -{ - struct - { - Node *root; /**< root node pointer */ - int (*compare)(void*, void*, int); /**< comparison function */ - } index[2]; - int indexes, /**< no of indexes into tree */ - count; /**< no of items */ - size_t size; /**< heap storage used */ - unsigned int heap_tracking : 1; /**< switch on heap tracking for this tree? */ - unsigned int allow_duplicates : 1; /**< switch to allow duplicate entries */ -} Tree; - - -Tree* TreeInitialize(int(*compare)(void*, void*, int)); -void TreeInitializeNoMalloc(Tree* aTree, int(*compare)(void*, void*, int)); -void TreeAddIndex(Tree* aTree, int(*compare)(void*, void*, int)); - -void* TreeAdd(Tree* aTree, void* content, size_t size); - -void* TreeRemove(Tree* aTree, void* content); - -void* TreeRemoveKey(Tree* aTree, void* key); -void* TreeRemoveKeyIndex(Tree* aTree, void* key, int index); - -void* TreeRemoveNodeIndex(Tree* aTree, Node* aNode, int index); - -void TreeFree(Tree* aTree); - -Node* TreeFind(Tree* aTree, void* key); -Node* TreeFindIndex(Tree* aTree, void* key, int index); - -Node* TreeNextElement(Tree* aTree, Node* curnode); - -int TreeIntCompare(void* a, void* b, int); -int TreePtrCompare(void* a, void* b, int); -int TreeStringCompare(void* a, void* b, int); - -#endif diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/VersionInfo.h.in b/src/communication/pub_gps/include/paho_mqtt_3c/VersionInfo.h.in deleted file mode 100644 index 5b91bf3..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/VersionInfo.h.in +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef VERSIONINFO_H -#define VERSIONINFO_H - -#define BUILD_TIMESTAMP "@BUILD_TIMESTAMP@" -#define CLIENT_VERSION "@CLIENT_VERSION@" - -#endif /* VERSIONINFO_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/WebSocket.h b/src/communication/pub_gps/include/paho_mqtt_3c/WebSocket.h deleted file mode 100644 index 33cc844..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/WebSocket.h +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Keith Holman - initial implementation and documentation - *******************************************************************************/ - -#if !defined(WEBSOCKET_H) -#define WEBSOCKET_H - -#include "Clients.h" - -/** - * WebSocket op codes - * @{ - */ -#define WebSocket_OP_CONTINUE 0x0 /* 0000 - continue frame */ -#define WebSocket_OP_TEXT 0x1 /* 0001 - text frame */ -#define WebSocket_OP_BINARY 0x2 /* 0010 - binary frame */ -#define WebSocket_OP_CLOSE 0x8 /* 1000 - close frame */ -#define WebSocket_OP_PING 0x9 /* 1001 - ping frame */ -#define WebSocket_OP_PONG 0xA /* 1010 - pong frame */ -/** @} */ - -/** - * Various close status codes - * @{ - */ -#define WebSocket_CLOSE_NORMAL 1000 -#define WebSocket_CLOSE_GOING_AWAY 1001 -#define WebSocket_CLOSE_PROTOCOL_ERROR 1002 -#define WebSocket_CLOSE_UNKNOWN_DATA 1003 -#define WebSocket_CLOSE_RESERVED 1004 -#define WebSocket_CLOSE_NO_STATUS_CODE 1005 /* reserved: not to be used */ -#define WebSocket_CLOSE_ABNORMAL 1006 /* reserved: not to be used */ -#define WebSocket_CLOSE_BAD_DATA 1007 -#define WebSocket_CLOSE_POLICY 1008 -#define WebSocket_CLOSE_MSG_TOO_BIG 1009 -#define WebSocket_CLOSE_NO_EXTENSION 1010 -#define WebScoket_CLOSE_UNEXPECTED 1011 -#define WebSocket_CLOSE_TLS_FAIL 1015 /* reserved: not be used */ -/** @} */ - -/* closes a websocket connection */ -void WebSocket_close(networkHandles *net, int status_code, const char *reason); - -/* sends upgrade request */ -int WebSocket_connect(networkHandles *net, const char *uri); - -/* calculates the extra data required in a packet to hold a WebSocket frame header */ -size_t WebSocket_calculateFrameHeaderSize(networkHandles *net, int mask_data, - size_t data_len); - -/* obtain data from network socket */ -int WebSocket_getch(networkHandles *net, char* c); -char *WebSocket_getdata(networkHandles *net, size_t bytes, size_t* actual_len); - -/* send data out, in websocket format only if required */ -int WebSocket_putdatas(networkHandles* net, char* buf0, size_t buf0len, - int count, char** buffers, size_t* buflens, int* freeData); - -/* releases any resources used by the websocket system */ -void WebSocket_terminate(void); - -/* handles websocket upgrade request */ -int WebSocket_upgrade(networkHandles *net); - -#endif /* WEBSOCKET_H */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/mutex_type.h b/src/communication/pub_gps/include/paho_mqtt_3c/mutex_type.h deleted file mode 100644 index 5760b37..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/mutex_type.h +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - *******************************************************************************/ -#if !defined(_MUTEX_TYPE_H_) -#define _MUTEX_TYPE_H_ - -#if defined(WIN32) || defined(WIN64) - #include - #define mutex_type HANDLE -#else - #include - #define mutex_type pthread_mutex_t* -#endif - -#endif /* _MUTEX_TYPE_H_ */ diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/pubsub_opts.h b/src/communication/pub_gps/include/paho_mqtt_3c/pubsub_opts.h deleted file mode 100644 index a506a68..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/pubsub_opts.h +++ /dev/null @@ -1,86 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2012, 2018 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial contribution - * Guilherme Maciel Ferreira - add keep alive option - *******************************************************************************/ - -#if !defined(PUBSUB_OPTS_H) -#define PUBSUB_OPTS_H - -#include "MQTTAsync.h" -#include "MQTTClientPersistence.h" - -struct pubsub_opts -{ - /* debug app options */ - int publisher; /* publisher app? */ - int quiet; - int verbose; - int tracelevel; - char* delimiter; - int maxdatalen; - /* message options */ - char* message; - char* filename; - int stdin_lines; - int stdlin_complete; - int null_message; - /* MQTT options */ - int MQTTVersion; - char* topic; - char* clientid; - int qos; - int retained; - char* username; - char* password; - char* host; - char* port; - char* connection; - int keepalive; - /* will options */ - char* will_topic; - char* will_payload; - int will_qos; - int will_retain; - /* TLS options */ - int insecure; - char* capath; - char* cert; - char* cafile; - char* key; - char* keypass; - char* ciphers; - /* MQTT V5 options */ - int message_expiry; - struct { - char *name; - char *value; - } user_property; -}; - -typedef struct -{ - const char* name; - const char* value; -} pubsub_opts_nameValue; - -//void usage(struct pubsub_opts* opts, const char* version, const char* program_name); -void usage(struct pubsub_opts* opts, pubsub_opts_nameValue* name_values, const char* program_name); -int getopts(int argc, char** argv, struct pubsub_opts* opts); -char* readfile(int* data_len, struct pubsub_opts* opts); -void logProperties(MQTTProperties *props); - -#endif - - diff --git a/src/communication/pub_gps/include/paho_mqtt_3c/utf-8.h b/src/communication/pub_gps/include/paho_mqtt_3c/utf-8.h deleted file mode 100644 index 8bce4b3..0000000 --- a/src/communication/pub_gps/include/paho_mqtt_3c/utf-8.h +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 IBM Corp. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v10.html - * and the Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Ian Craggs - initial API and implementation and/or initial documentation - *******************************************************************************/ - -#if !defined(UTF8_H) -#define UTF8_H - -int UTF8_validate(int len, const char *data); -int UTF8_validateString(const char* string); - -#endif diff --git a/src/communication/pub_gps/include/pub_gps/json.h b/src/communication/pub_gps/include/pub_gps/json.h deleted file mode 100644 index d95fe6e..0000000 --- a/src/communication/pub_gps/include/pub_gps/json.h +++ /dev/null @@ -1,2351 +0,0 @@ -/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/). -/// It is intended to be used with #include "json/json.h" - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and -The JsonCpp Authors, and is released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - -#ifndef JSON_AMALGAMATED_H_INCLUDED -# define JSON_AMALGAMATED_H_INCLUDED -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -#define JSON_IS_AMALGAMATION - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - -#ifndef JSON_VERSION_H_INCLUDED -#define JSON_VERSION_H_INCLUDED - -// Note: version must be updated in three places when doing a release. This -// annoying process ensures that amalgamate, CMake, and meson all report the -// correct version. -// 1. /meson.build -// 2. /include/json/version.h -// 3. /CMakeLists.txt -// IMPORTANT: also update the SOVERSION!! - -#define JSONCPP_VERSION_STRING "1.9.5" -#define JSONCPP_VERSION_MAJOR 1 -#define JSONCPP_VERSION_MINOR 9 -#define JSONCPP_VERSION_PATCH 5 -#define JSONCPP_VERSION_QUALIFIER -#define JSONCPP_VERSION_HEXA \ - ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ - (JSONCPP_VERSION_PATCH << 8)) - -#ifdef JSONCPP_USING_SECURE_MEMORY -#undef JSONCPP_USING_SECURE_MEMORY -#endif -#define JSONCPP_USING_SECURE_MEMORY 0 -// If non-zero, the library zeroes any memory that it has allocated before -// it frees its memory. - -#endif // JSON_VERSION_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/version.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/allocator.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_ALLOCATOR_H_INCLUDED -#define JSON_ALLOCATOR_H_INCLUDED - -#include -#include - -#pragma pack(push) -#pragma pack() - -namespace Json { -template class SecureAllocator { -public: - // Type definitions - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - /** - * Allocate memory for N items using the standard allocator. - */ - pointer allocate(size_type n) { - // allocate using "global operator new" - return static_cast(::operator new(n * sizeof(T))); - } - - /** - * Release memory which was allocated for N items at pointer P. - * - * The memory block is filled with zeroes before being released. - */ - void deallocate(pointer p, size_type n) { - // memset_s is used because memset may be optimized away by the compiler - memset_s(p, n * sizeof(T), 0, n * sizeof(T)); - // free using "global operator delete" - ::operator delete(p); - } - - /** - * Construct an item in-place at pointer P. - */ - template void construct(pointer p, Args&&... args) { - // construct using "placement new" and "perfect forwarding" - ::new (static_cast(p)) T(std::forward(args)...); - } - - size_type max_size() const { return size_t(-1) / sizeof(T); } - - pointer address(reference x) const { return std::addressof(x); } - - const_pointer address(const_reference x) const { return std::addressof(x); } - - /** - * Destroy an item in-place at pointer P. - */ - void destroy(pointer p) { - // destroy using "explicit destructor" - p->~T(); - } - - // Boilerplate - SecureAllocator() {} - template SecureAllocator(const SecureAllocator&) {} - template struct rebind { using other = SecureAllocator; }; -}; - -template -bool operator==(const SecureAllocator&, const SecureAllocator&) { - return true; -} - -template -bool operator!=(const SecureAllocator&, const SecureAllocator&) { - return false; -} - -} // namespace Json - -#pragma pack(pop) - -#endif // JSON_ALLOCATOR_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/allocator.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_CONFIG_H_INCLUDED -#define JSON_CONFIG_H_INCLUDED -#include -#include -#include -#include -#include -#include -#include -#include - -// If non-zero, the library uses exceptions to report bad input instead of C -// assertion macros. The default is to use exceptions. -#ifndef JSON_USE_EXCEPTION -#define JSON_USE_EXCEPTION 1 -#endif - -// Temporary, tracked for removal with issue #982. -#ifndef JSON_USE_NULLREF -#define JSON_USE_NULLREF 1 -#endif - -/// If defined, indicates that the source file is amalgamated -/// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgamated header. -// #define JSON_IS_AMALGAMATION - -// Export macros for DLL visibility -#if defined(JSON_DLL_BUILD) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllexport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#elif defined(__GNUC__) || defined(__clang__) -#define JSON_API __attribute__((visibility("default"))) -#endif // if defined(_MSC_VER) - -#elif defined(JSON_DLL) -#if defined(_MSC_VER) || defined(__MINGW32__) -#define JSON_API __declspec(dllimport) -#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING -#endif // if defined(_MSC_VER) -#endif // ifdef JSON_DLL_BUILD - -#if !defined(JSON_API) -#define JSON_API -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1800 -#error \ - "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" -#endif - -#if defined(_MSC_VER) && _MSC_VER < 1900 -// As recommended at -// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 -extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, - const char* format, ...); -#define jsoncpp_snprintf msvc_pre1900_c99_snprintf -#else -#define jsoncpp_snprintf std::snprintf -#endif - -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 - -// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. -// C++11 should be used directly in JSONCPP. -#define JSONCPP_OVERRIDE override - -#ifdef __clang__ -#if __has_extension(attribute_deprecated_with_message) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#endif -#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) -#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -#endif // GNUC version -#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates - // MSVC) -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#endif // __clang__ || __GNUC__ || _MSC_VER - -#if !defined(JSONCPP_DEPRECATED) -#define JSONCPP_DEPRECATED(message) -#endif // if !defined(JSONCPP_DEPRECATED) - -#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) -#define JSON_USE_INT64_DOUBLE_CONVERSION 1 -#endif - -#if !defined(JSON_IS_AMALGAMATION) - -#include "allocator.h" -#include "version.h" - -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { -using Int = int; -using UInt = unsigned int; -#if defined(JSON_NO_INT64) -using LargestInt = int; -using LargestUInt = unsigned int; -#undef JSON_HAS_INT64 -#else // if defined(JSON_NO_INT64) -// For Microsoft Visual use specific types as long long is not supported -#if defined(_MSC_VER) // Microsoft Visual Studio -using Int64 = __int64; -using UInt64 = unsigned __int64; -#else // if defined(_MSC_VER) // Other platforms, use long long -using Int64 = int64_t; -using UInt64 = uint64_t; -#endif // if defined(_MSC_VER) -using LargestInt = Int64; -using LargestUInt = UInt64; -#define JSON_HAS_INT64 -#endif // if defined(JSON_NO_INT64) - -template -using Allocator = - typename std::conditional, - std::allocator>::type; -using String = std::basic_string, Allocator>; -using IStringStream = - std::basic_istringstream; -using OStringStream = - std::basic_ostringstream; -using IStream = std::istream; -using OStream = std::ostream; -} // namespace Json - -// Legacy names (formerly macros). -using JSONCPP_STRING = Json::String; -using JSONCPP_ISTRINGSTREAM = Json::IStringStream; -using JSONCPP_OSTRINGSTREAM = Json::OStringStream; -using JSONCPP_ISTREAM = Json::IStream; -using JSONCPP_OSTREAM = Json::OStream; - -#endif // JSON_CONFIG_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/config.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FORWARDS_H_INCLUDED -#define JSON_FORWARDS_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -// writer.h -class StreamWriter; -class StreamWriterBuilder; -class Writer; -class FastWriter; -class StyledWriter; -class StyledStreamWriter; - -// reader.h -class Reader; -class CharReader; -class CharReaderBuilder; - -// json_features.h -class Features; - -// value.h -using ArrayIndex = unsigned int; -class StaticString; -class Path; -class PathArgument; -class Value; -class ValueIteratorBase; -class ValueIterator; -class ValueConstIterator; - -} // namespace Json - -#endif // JSON_FORWARDS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/forwards.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/json_features.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_FEATURES_H_INCLUDED -#define JSON_FEATURES_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -#pragma pack(push) -#pragma pack() - -namespace Json { - -/** \brief Configuration passed to reader and writer. - * This configuration object can be used to force the Reader or Writer - * to behave in a standard conforming way. - */ -class JSON_API Features { -public: - /** \brief A configuration that allows all features and assumes all strings - * are UTF-8. - * - C & C++ comments are allowed - * - Root object can be any JSON value - * - Assumes Value strings are encoded in UTF-8 - */ - static Features all(); - - /** \brief A configuration that is strictly compatible with the JSON - * specification. - * - Comments are forbidden. - * - Root object must be either an array or an object value. - * - Assumes Value strings are encoded in UTF-8 - */ - static Features strictMode(); - - /** \brief Initialize the configuration like JsonConfig::allFeatures; - */ - Features(); - - /// \c true if comments are allowed. Default: \c true. - bool allowComments_{true}; - - /// \c true if root must be either an array or an object value. Default: \c - /// false. - bool strictRoot_{false}; - - /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_{false}; - - /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_{false}; -}; - -} // namespace Json - -#pragma pack(pop) - -#endif // JSON_FEATURES_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/json_features.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_H_INCLUDED -#define JSON_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "forwards.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -// Conditional NORETURN attribute on the throw functions would: -// a) suppress false positives from static code analysis -// b) possibly improve optimization opportunities. -#if !defined(JSONCPP_NORETURN) -#if defined(_MSC_VER) && _MSC_VER == 1800 -#define JSONCPP_NORETURN __declspec(noreturn) -#else -#define JSONCPP_NORETURN [[noreturn]] -#endif -#endif - -// Support for '= delete' with template declarations was a late addition -// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2 -// even though these declare themselves to be c++11 compilers. -#if !defined(JSONCPP_TEMPLATE_DELETE) -#if defined(__clang__) && defined(__apple_build_version__) -#if __apple_build_version__ <= 8000042 -#define JSONCPP_TEMPLATE_DELETE -#endif -#elif defined(__clang__) -#if __clang_major__ == 3 && __clang_minor__ <= 8 -#define JSONCPP_TEMPLATE_DELETE -#endif -#endif -#if !defined(JSONCPP_TEMPLATE_DELETE) -#define JSONCPP_TEMPLATE_DELETE = delete -#endif -#endif - -#include -#include -#include -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251 4275) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push) -#pragma pack() - -/** \brief JSON (JavaScript Object Notation). - */ -namespace Json { - -#if JSON_USE_EXCEPTION -/** Base class for all exceptions we throw. - * - * We use nothing but these internally. Of course, STL can throw others. - */ -class JSON_API Exception : public std::exception { -public: - Exception(String msg); - ~Exception() noexcept override; - char const* what() const noexcept override; - -protected: - String msg_; -}; - -/** Exceptions which the user cannot easily avoid. - * - * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input - * - * \remark derived from Json::Exception - */ -class JSON_API RuntimeError : public Exception { -public: - RuntimeError(String const& msg); -}; - -/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. - * - * These are precondition-violations (user bugs) and internal errors (our bugs). - * - * \remark derived from Json::Exception - */ -class JSON_API LogicError : public Exception { -public: - LogicError(String const& msg); -}; -#endif - -/// used internally -JSONCPP_NORETURN void throwRuntimeError(String const& msg); -/// used internally -JSONCPP_NORETURN void throwLogicError(String const& msg); - -/** \brief Type of the value held by a Value object. - */ -enum ValueType { - nullValue = 0, ///< 'null' value - intValue, ///< signed integer value - uintValue, ///< unsigned integer value - realValue, ///< double value - stringValue, ///< UTF-8 string value - booleanValue, ///< bool value - arrayValue, ///< array value (ordered list) - objectValue ///< object value (collection of name/value pairs). -}; - -enum CommentPlacement { - commentBefore = 0, ///< a comment placed on the line before a value - commentAfterOnSameLine, ///< a comment just after a value on the same line - commentAfter, ///< a comment on the line after a value (only make sense for - /// root value) - numberOfCommentPlacement -}; - -/** \brief Type of precision for formatting of real values. - */ -enum PrecisionType { - significantDigits = 0, ///< we set max number of significant digits in string - decimalPlaces ///< we set max number of digits after "." in string -}; - -/** \brief Lightweight wrapper to tag static string. - * - * Value constructor and objectValue member assignment takes advantage of the - * StaticString and avoid the cost of string duplication when storing the - * string or the member name. - * - * Example of usage: - * \code - * Json::Value aValue( StaticString("some text") ); - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ -class JSON_API StaticString { -public: - explicit StaticString(const char* czstring) : c_str_(czstring) {} - - operator const char*() const { return c_str_; } - - const char* c_str() const { return c_str_; } - -private: - const char* c_str_; -}; - -/** \brief Represents a JSON value. - * - * This class is a discriminated union wrapper that can represents a: - * - signed integer [range: Value::minInt - Value::maxInt] - * - unsigned integer (range: 0 - Value::maxUInt) - * - double - * - UTF-8 string - * - boolean - * - 'null' - * - an ordered list of Value - * - collection of name/value pairs (javascript object) - * - * The type of the held value is represented by a #ValueType and - * can be obtained using type(). - * - * Values of an #objectValue or #arrayValue can be accessed using operator[]() - * methods. - * Non-const methods will automatically create the a #nullValue element - * if it does not exist. - * The sequence of an #arrayValue will be automatically resized and initialized - * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. - * - * The get() methods can be used to obtain default value in the case the - * required element does not exist. - * - * It is possible to iterate over the list of member keys of an object using - * the getMemberNames() method. - * - * \note #Value string-length fit in size_t, but keys must be < 2^30. - * (The reason is an implementation detail.) A #CharReader will raise an - * exception if a bound is exceeded to avoid security holes in your app, - * but the Value API does *not* check bounds. That is the responsibility - * of the caller. - */ -class JSON_API Value { - friend class ValueIteratorBase; - -public: - using Members = std::vector; - using iterator = ValueIterator; - using const_iterator = ValueConstIterator; - using UInt = Json::UInt; - using Int = Json::Int; -#if defined(JSON_HAS_INT64) - using UInt64 = Json::UInt64; - using Int64 = Json::Int64; -#endif // defined(JSON_HAS_INT64) - using LargestInt = Json::LargestInt; - using LargestUInt = Json::LargestUInt; - using ArrayIndex = Json::ArrayIndex; - - // Required for boost integration, e. g. BOOST_TEST - using value_type = std::string; - -#if JSON_USE_NULLREF - // Binary compatibility kludges, do not use. - static const Value& null; - static const Value& nullRef; -#endif - - // null and nullRef are deprecated, use this instead. - static Value const& nullSingleton(); - - /// Minimum signed integer value that can be stored in a Json::Value. - static constexpr LargestInt minLargestInt = - LargestInt(~(LargestUInt(-1) / 2)); - /// Maximum signed integer value that can be stored in a Json::Value. - static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); - /// Maximum unsigned integer value that can be stored in a Json::Value. - static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); - - /// Minimum signed int value that can be stored in a Json::Value. - static constexpr Int minInt = Int(~(UInt(-1) / 2)); - /// Maximum signed int value that can be stored in a Json::Value. - static constexpr Int maxInt = Int(UInt(-1) / 2); - /// Maximum unsigned int value that can be stored in a Json::Value. - static constexpr UInt maxUInt = UInt(-1); - -#if defined(JSON_HAS_INT64) - /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); - /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); - /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static constexpr UInt64 maxUInt64 = UInt64(-1); -#endif // defined(JSON_HAS_INT64) - /// Default precision for real value for string representation. - static constexpr UInt defaultRealPrecision = 17; - // The constant is hard-coded because some compiler have trouble - // converting Value::maxUInt64 to a double correctly (AIX/xlC). - // Assumes that UInt64 is a 64 bits integer. - static constexpr double maxUInt64AsDouble = 18446744073709551615.0; -// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler -// when using gcc and clang backend compilers. CZString -// cannot be defined as private. See issue #486 -#ifdef __NVCC__ -public: -#else -private: -#endif -#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - class CZString { - public: - enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; - CZString(ArrayIndex index); - CZString(char const* str, unsigned length, DuplicationPolicy allocate); - CZString(CZString const& other); - CZString(CZString&& other) noexcept; - ~CZString(); - CZString& operator=(const CZString& other); - CZString& operator=(CZString&& other) noexcept; - - bool operator<(CZString const& other) const; - bool operator==(CZString const& other) const; - ArrayIndex index() const; - // const char* c_str() const; ///< \deprecated - char const* data() const; - unsigned length() const; - bool isStaticString() const; - - private: - void swap(CZString& other); - - struct StringStorage { - unsigned policy_ : 2; - unsigned length_ : 30; // 1GB max - }; - - char const* cstr_; // actually, a prefixed string, unless policy is noDup - union { - ArrayIndex index_; - StringStorage storage_; - }; - }; - -public: - typedef std::map ObjectValues; -#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION - -public: - /** - * \brief Create a default Value of the given type. - * - * This is a very useful constructor. - * To create an empty array, pass arrayValue. - * To create an empty object, pass objectValue. - * Another Value can then be set to this one by assignment. - * This is useful since clear() and resize() will not alter types. - * - * Examples: - * \code - * Json::Value null_value; // null - * Json::Value arr_value(Json::arrayValue); // [] - * Json::Value obj_value(Json::objectValue); // {} - * \endcode - */ - Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); - Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) - Value(const char* begin, const char* end); ///< Copy all, incl zeroes. - /** - * \brief Constructs a value from a static string. - * - * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to - * this constructor. - * - * \note This works only for null-terminated strings. (We cannot change the - * size of this class, so we have nowhere to store the length, which might be - * computed later for various operations.) - * - * Example of usage: - * \code - * static StaticString foo("some text"); - * Json::Value aValue(foo); - * \endcode - */ - Value(const StaticString& value); - Value(const String& value); - Value(bool value); - Value(std::nullptr_t ptr) = delete; - Value(const Value& other); - Value(Value&& other) noexcept; - ~Value(); - - /// \note Overwrite existing comments. To preserve comments, use - /// #swapPayload(). - Value& operator=(const Value& other); - Value& operator=(Value&& other) noexcept; - - /// Swap everything. - void swap(Value& other); - /// Swap values but leave comments and source offsets in place. - void swapPayload(Value& other); - - /// copy everything. - void copy(const Value& other); - /// copy values but leave comments and source offsets in place. - void copyPayload(const Value& other); - - ValueType type() const; - - /// Compare payload only, not comments etc. - bool operator<(const Value& other) const; - bool operator<=(const Value& other) const; - bool operator>=(const Value& other) const; - bool operator>(const Value& other) const; - bool operator==(const Value& other) const; - bool operator!=(const Value& other) const; - int compare(const Value& other) const; - - const char* asCString() const; ///< Embedded zeroes could cause you trouble! -#if JSONCPP_USING_SECURE_MEMORY - unsigned getCStringLength() const; // Allows you to understand the length of - // the CString -#endif - String asString() const; ///< Embedded zeroes are possible. - /** Get raw char* of string-value. - * \return false if !string. (Seg-fault if str or end are NULL.) - */ - bool getString(char const** begin, char const** end) const; - Int asInt() const; - UInt asUInt() const; -#if defined(JSON_HAS_INT64) - Int64 asInt64() const; - UInt64 asUInt64() const; -#endif // if defined(JSON_HAS_INT64) - LargestInt asLargestInt() const; - LargestUInt asLargestUInt() const; - float asFloat() const; - double asDouble() const; - bool asBool() const; - - bool isNull() const; - bool isBool() const; - bool isInt() const; - bool isInt64() const; - bool isUInt() const; - bool isUInt64() const; - bool isIntegral() const; - bool isDouble() const; - bool isNumeric() const; - bool isString() const; - bool isArray() const; - bool isObject() const; - - /// The `as` and `is` member function templates and specializations. - template T as() const JSONCPP_TEMPLATE_DELETE; - template bool is() const JSONCPP_TEMPLATE_DELETE; - - bool isConvertibleTo(ValueType other) const; - - /// Number of values in array or object - ArrayIndex size() const; - - /// \brief Return true if empty array, empty object, or null; - /// otherwise, false. - bool empty() const; - - /// Return !isNull() - explicit operator bool() const; - - /// Remove all object members and array elements. - /// \pre type() is arrayValue, objectValue, or nullValue - /// \post type() is unchanged - void clear(); - - /// Resize the array to newSize elements. - /// New elements are initialized to null. - /// May only be called on nullValue or arrayValue. - /// \pre type() is arrayValue or nullValue - /// \post type() is arrayValue - void resize(ArrayIndex newSize); - - ///@{ - /// Access an array element (zero based index). If the array contains less - /// than index element, then null value are inserted in the array so that - /// its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - Value& operator[](ArrayIndex index); - Value& operator[](int index); - ///@} - - ///@{ - /// Access an array element (zero based index). - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) - const Value& operator[](ArrayIndex index) const; - const Value& operator[](int index) const; - ///@} - - /// If the array contains at least index+1 elements, returns the element - /// value, otherwise returns defaultValue. - Value get(ArrayIndex index, const Value& defaultValue) const; - /// Return true if index < size(). - bool isValidIndex(ArrayIndex index) const; - /// \brief Append value to array at the end. - /// - /// Equivalent to jsonvalue[jsonvalue.size()] = value; - Value& append(const Value& value); - Value& append(Value&& value); - - /// \brief Insert value in array at specific index - bool insert(ArrayIndex index, const Value& newValue); - bool insert(ArrayIndex index, Value&& newValue); - - /// Access an object value by name, create a null member if it does not exist. - /// \note Because of our implementation, keys are limited to 2^30 -1 chars. - /// Exceeding that will cause an exception. - Value& operator[](const char* key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const char* key) const; - /// Access an object value by name, create a null member if it does not exist. - /// \param key may contain embedded nulls. - Value& operator[](const String& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - /// \param key may contain embedded nulls. - const Value& operator[](const String& key) const; - /** \brief Access an object value by name, create a null member if it does not - * exist. - * - * If the object has no entry for that name, then the member name used to - * store the new entry is not duplicated. - * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode - */ - Value& operator[](const StaticString& key); - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const char* key, const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \note key may contain embedded nulls. - Value get(const char* begin, const char* end, - const Value& defaultValue) const; - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - /// \param key may contain embedded nulls. - Value get(const String& key, const Value& defaultValue) const; - /// Most general and efficient version of isMember()const, get()const, - /// and operator[]const - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - Value const* find(char const* begin, char const* end) const; - /// Most general and efficient version of object-mutators. - /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 - /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. - Value* demand(char const* begin, char const* end); - /// \brief Remove and return the named member. - /// - /// Do nothing if it did not exist. - /// \pre type() is objectValue or nullValue - /// \post type() is unchanged - void removeMember(const char* key); - /// Same as removeMember(const char*) - /// \param key may contain embedded nulls. - void removeMember(const String& key); - /// Same as removeMember(const char* begin, const char* end, Value* removed), - /// but 'key' is null-terminated. - bool removeMember(const char* key, Value* removed); - /** \brief Remove the named map member. - * - * Update 'removed' iff removed. - * \param key may contain embedded nulls. - * \return true iff removed (no exceptions) - */ - bool removeMember(String const& key, Value* removed); - /// Same as removeMember(String const& key, Value* removed) - bool removeMember(const char* begin, const char* end, Value* removed); - /** \brief Remove the indexed array element. - * - * O(n) expensive operations. - * Update 'removed' iff removed. - * \return true if removed (no exceptions) - */ - bool removeIndex(ArrayIndex index, Value* removed); - - /// Return true if the object has a member named key. - /// \note 'key' must be null-terminated. - bool isMember(const char* key) const; - /// Return true if the object has a member named key. - /// \param key may contain embedded nulls. - bool isMember(const String& key) const; - /// Same as isMember(String const& key)const - bool isMember(const char* begin, const char* end) const; - - /// \brief Return a list of the member names. - /// - /// If null, return an empty list. - /// \pre type() is objectValue or nullValue - /// \post if type() was nullValue, it remains nullValue - Members getMemberNames() const; - - /// \deprecated Always pass len. - JSONCPP_DEPRECATED("Use setComment(String const&) instead.") - void setComment(const char* comment, CommentPlacement placement) { - setComment(String(comment, strlen(comment)), placement); - } - /// Comments must be //... or /* ... */ - void setComment(const char* comment, size_t len, CommentPlacement placement) { - setComment(String(comment, len), placement); - } - /// Comments must be //... or /* ... */ - void setComment(String comment, CommentPlacement placement); - bool hasComment(CommentPlacement placement) const; - /// Include delimiters and embedded newlines. - String getComment(CommentPlacement placement) const; - - String toStyledString() const; - - const_iterator begin() const; - const_iterator end() const; - - iterator begin(); - iterator end(); - - // Accessors for the [start, limit) range of bytes within the JSON text from - // which this value was parsed, if any. - void setOffsetStart(ptrdiff_t start); - void setOffsetLimit(ptrdiff_t limit); - ptrdiff_t getOffsetStart() const; - ptrdiff_t getOffsetLimit() const; - -private: - void setType(ValueType v) { - bits_.value_type_ = static_cast(v); - } - bool isAllocated() const { return bits_.allocated_; } - void setIsAllocated(bool v) { bits_.allocated_ = v; } - - void initBasic(ValueType type, bool allocated = false); - void dupPayload(const Value& other); - void releasePayload(); - void dupMeta(const Value& other); - - Value& resolveReference(const char* key); - Value& resolveReference(const char* key, const char* end); - - // struct MemberNamesTransform - //{ - // typedef const char *result_type; - // const char *operator()( const CZString &name ) const - // { - // return name.c_str(); - // } - //}; - - union ValueHolder { - LargestInt int_; - LargestUInt uint_; - double real_; - bool bool_; - char* string_; // if allocated_, ptr to { unsigned, char[] }. - ObjectValues* map_; - } value_; - - struct { - // Really a ValueType, but types should agree for bitfield packing. - unsigned int value_type_ : 8; - // Unless allocated_, string_ must be null-terminated. - unsigned int allocated_ : 1; - } bits_; - - class Comments { - public: - Comments() = default; - Comments(const Comments& that); - Comments(Comments&& that) noexcept; - Comments& operator=(const Comments& that); - Comments& operator=(Comments&& that) noexcept; - bool has(CommentPlacement slot) const; - String get(CommentPlacement slot) const; - void set(CommentPlacement slot, String comment); - - private: - using Array = std::array; - std::unique_ptr ptr_; - }; - Comments comments_; - - // [start, limit) byte offsets in the source JSON text from which this Value - // was extracted. - ptrdiff_t start_; - ptrdiff_t limit_; -}; - -template <> inline bool Value::as() const { return asBool(); } -template <> inline bool Value::is() const { return isBool(); } - -template <> inline Int Value::as() const { return asInt(); } -template <> inline bool Value::is() const { return isInt(); } - -template <> inline UInt Value::as() const { return asUInt(); } -template <> inline bool Value::is() const { return isUInt(); } - -#if defined(JSON_HAS_INT64) -template <> inline Int64 Value::as() const { return asInt64(); } -template <> inline bool Value::is() const { return isInt64(); } - -template <> inline UInt64 Value::as() const { return asUInt64(); } -template <> inline bool Value::is() const { return isUInt64(); } -#endif - -template <> inline double Value::as() const { return asDouble(); } -template <> inline bool Value::is() const { return isDouble(); } - -template <> inline String Value::as() const { return asString(); } -template <> inline bool Value::is() const { return isString(); } - -/// These `as` specializations are type conversions, and do not have a -/// corresponding `is`. -template <> inline float Value::as() const { return asFloat(); } -template <> inline const char* Value::as() const { - return asCString(); -} - -/** \brief Experimental and untested: represents an element of the "path" to - * access a node. - */ -class JSON_API PathArgument { -public: - friend class Path; - - PathArgument(); - PathArgument(ArrayIndex index); - PathArgument(const char* key); - PathArgument(String key); - -private: - enum Kind { kindNone = 0, kindIndex, kindKey }; - String key_; - ArrayIndex index_{}; - Kind kind_{kindNone}; -}; - -/** \brief Experimental and untested: represents a "path" to access a node. - * - * Syntax: - * - "." => root node - * - ".[n]" => elements at index 'n' of root node (an array value) - * - ".name" => member named 'name' of root node (an object value) - * - ".name1.name2.name3" - * - ".[0][1][2].name1[3]" - * - ".%" => member name is provided as parameter - * - ".[%]" => index is provided as parameter - */ -class JSON_API Path { -public: - Path(const String& path, const PathArgument& a1 = PathArgument(), - const PathArgument& a2 = PathArgument(), - const PathArgument& a3 = PathArgument(), - const PathArgument& a4 = PathArgument(), - const PathArgument& a5 = PathArgument()); - - const Value& resolve(const Value& root) const; - Value resolve(const Value& root, const Value& defaultValue) const; - /// Creates the "path" to access the specified node and returns a reference on - /// the node. - Value& make(Value& root) const; - -private: - using InArgs = std::vector; - using Args = std::vector; - - void makePath(const String& path, const InArgs& in); - void addPathInArg(const String& path, const InArgs& in, - InArgs::const_iterator& itInArg, PathArgument::Kind kind); - static void invalidPath(const String& path, int location); - - Args args_; -}; - -/** \brief base class for Value iterators. - * - */ -class JSON_API ValueIteratorBase { -public: - using iterator_category = std::bidirectional_iterator_tag; - using size_t = unsigned int; - using difference_type = int; - using SelfType = ValueIteratorBase; - - bool operator==(const SelfType& other) const { return isEqual(other); } - - bool operator!=(const SelfType& other) const { return !isEqual(other); } - - difference_type operator-(const SelfType& other) const { - return other.computeDistance(*this); - } - - /// Return either the index or the member name of the referenced value as a - /// Value. - Value key() const; - - /// Return the index of the referenced Value, or -1 if it is not an - /// arrayValue. - UInt index() const; - - /// Return the member name of the referenced Value, or "" if it is not an - /// objectValue. - /// \note Avoid `c_str()` on result, as embedded zeroes are possible. - String name() const; - - /// Return the member name of the referenced Value. "" if it is not an - /// objectValue. - /// \deprecated This cannot be used for UTF-8 strings, since there can be - /// embedded nulls. - JSONCPP_DEPRECATED("Use `key = name();` instead.") - char const* memberName() const; - /// Return the member name of the referenced Value, or NULL if it is not an - /// objectValue. - /// \note Better version than memberName(). Allows embedded nulls. - char const* memberName(char const** end) const; - -protected: - /*! Internal utility functions to assist with implementing - * other iterator functions. The const and non-const versions - * of the "deref" protected methods expose the protected - * current_ member variable in a way that can often be - * optimized away by the compiler. - */ - const Value& deref() const; - Value& deref(); - - void increment(); - - void decrement(); - - difference_type computeDistance(const SelfType& other) const; - - bool isEqual(const SelfType& other) const; - - void copy(const SelfType& other); - -private: - Value::ObjectValues::iterator current_; - // Indicates that iterator is for a null value. - bool isNull_{true}; - -public: - // For some reason, BORLAND needs these at the end, rather - // than earlier. No idea why. - ValueIteratorBase(); - explicit ValueIteratorBase(const Value::ObjectValues::iterator& current); -}; - -/** \brief const iterator for object and array value. - * - */ -class JSON_API ValueConstIterator : public ValueIteratorBase { - friend class Value; - -public: - using value_type = const Value; - // typedef unsigned int size_t; - // typedef int difference_type; - using reference = const Value&; - using pointer = const Value*; - using SelfType = ValueConstIterator; - - ValueConstIterator(); - ValueConstIterator(ValueIterator const& other); - -private: - /*! \internal Use by Value to create an iterator. - */ - explicit ValueConstIterator(const Value::ObjectValues::iterator& current); - -public: - SelfType& operator=(const ValueIteratorBase& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } -}; - -/** \brief Iterator for object and array value. - */ -class JSON_API ValueIterator : public ValueIteratorBase { - friend class Value; - -public: - using value_type = Value; - using size_t = unsigned int; - using difference_type = int; - using reference = Value&; - using pointer = Value*; - using SelfType = ValueIterator; - - ValueIterator(); - explicit ValueIterator(const ValueConstIterator& other); - ValueIterator(const ValueIterator& other); - -private: - /*! \internal Use by Value to create an iterator. - */ - explicit ValueIterator(const Value::ObjectValues::iterator& current); - -public: - SelfType& operator=(const SelfType& other); - - SelfType operator++(int) { - SelfType temp(*this); - ++*this; - return temp; - } - - SelfType operator--(int) { - SelfType temp(*this); - --*this; - return temp; - } - - SelfType& operator--() { - decrement(); - return *this; - } - - SelfType& operator++() { - increment(); - return *this; - } - - /*! The return value of non-const iterators can be - * changed, so the these functions are not const - * because the returned references/pointers can be used - * to change state of the base class. - */ - reference operator*() const { return const_cast(deref()); } - pointer operator->() const { return const_cast(&deref()); } -}; - -inline void swap(Value& a, Value& b) { a.swap(b); } - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/value.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_READER_H_INCLUDED -#define JSON_READER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "json_features.h" -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push) -#pragma pack() - -namespace Json { - -/** \brief Unserialize a JSON document into a - * Value. - * - * \deprecated Use CharReader and CharReaderBuilder. - */ - -class JSON_API Reader { -public: - using Char = char; - using Location = const Char*; - - /** \brief An error tagged with where in the JSON text it was encountered. - * - * The offsets give the [start, limit) range of bytes within the text. Note - * that this is bytes, not codepoints. - */ - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; - - /** \brief Constructs a Reader allowing all features for parsing. - * \deprecated Use CharReader and CharReaderBuilder. - */ - Reader(); - - /** \brief Constructs a Reader allowing the specified feature set for parsing. - * \deprecated Use CharReader and CharReaderBuilder. - */ - Reader(const Features& features); - - /** \brief Read a Value from a JSON - * document. - * - * \param document UTF-8 encoded string containing the document - * to read. - * \param[out] root Contains the root value of the document if it - * was successfully parsed. - * \param collectComments \c true to collect comment and allow writing - * them back during serialization, \c false to - * discard comments. This parameter is ignored - * if Features::allowComments_ is \c false. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - bool parse(const std::string& document, Value& root, - bool collectComments = true); - - /** \brief Read a Value from a JSON - * document. - * - * \param beginDoc Pointer on the beginning of the UTF-8 encoded - * string of the document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string - * of the document to read. Must be >= beginDoc. - * \param[out] root Contains the root value of the document if it - * was successfully parsed. - * \param collectComments \c true to collect comment and allow writing - * them back during serialization, \c false to - * discard comments. This parameter is ignored - * if Features::allowComments_ is \c false. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - bool parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments = true); - - /// \brief Parse from input stream. - /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(IStream& is, Value& root, bool collectComments = true); - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * - * \return Formatted error message with the list of errors with their - * location in the parsed document. An empty string is returned if no error - * occurred during parsing. - * \deprecated Use getFormattedErrorMessages() instead (typo fix). - */ - JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") - String getFormatedErrorMessages() const; - - /** \brief Returns a user friendly string that list errors in the parsed - * document. - * - * \return Formatted error message with the list of errors with their - * location in the parsed document. An empty string is returned if no error - * occurred during parsing. - */ - String getFormattedErrorMessages() const; - - /** \brief Returns a vector of structured errors encountered while parsing. - * - * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate multiple - * errors. This can occur if the parser recovers from a non-fatal parse - * error and then encounters additional errors. - */ - std::vector getStructuredErrors() const; - - /** \brief Add a semantic error message. - * - * \param value JSON Value location associated with the error - * \param message The error message. - * \return \c true if the error was successfully added, \c false if the Value - * offset exceeds the document size. - */ - bool pushError(const Value& value, const String& message); - - /** \brief Add a semantic error message with extra context. - * - * \param value JSON Value location associated with the error - * \param message The error message. - * \param extra Additional JSON Value location to contextualize the error - * \return \c true if the error was successfully added, \c false if either - * Value offset exceeds the document size. - */ - bool pushError(const Value& value, const String& message, const Value& extra); - - /** \brief Return whether there are any errors. - * - * \return \c true if there are no errors to report \c false if errors have - * occurred. - */ - bool good() const; - -private: - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - String message_; - Location extra_; - }; - - using Errors = std::deque; - - bool readToken(Token& token); - void skipSpaces(); - bool match(const Char* pattern, int patternLength); - bool readComment(); - bool readCStyleComment(); - bool readCppStyleComment(); - bool readString(); - void readNumber(); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, String& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, unsigned int& unicode); - bool addError(const String& message, Token& token, Location extra = nullptr); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const String& message, Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void getLocationLineAndColumn(Location location, int& line, - int& column) const; - String getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - static bool containsNewLine(Location begin, Location end); - static String normalizeEOL(Location begin, Location end); - - using Nodes = std::stack; - Nodes nodes_; - Errors errors_; - String document_; - Location begin_{}; - Location end_{}; - Location current_{}; - Location lastValueEnd_{}; - Value* lastValue_{}; - String commentsBefore_; - Features features_; - bool collectComments_{}; -}; // Reader - -/** Interface for reading JSON from a char array. - */ -class JSON_API CharReader { -public: - virtual ~CharReader() = default; - /** \brief Read a Value from a JSON - * document. The document must be a UTF-8 encoded string containing the - * document to read. - * - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string - * of the document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - * document to read. Must be >= beginDoc. - * \param[out] root Contains the root value of the document if it was - * successfully parsed. - * \param[out] errs Formatted error messages (if not NULL) a user - * friendly string that lists errors in the parsed - * document. - * \return \c true if the document was successfully parsed, \c false if an - * error occurred. - */ - virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) = 0; - - class JSON_API Factory { - public: - virtual ~Factory() = default; - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual CharReader* newCharReader() const = 0; - }; // Factory -}; // CharReader - -/** \brief Build a CharReader implementation. - * - * Usage: - * \code - * using namespace Json; - * CharReaderBuilder builder; - * builder["collectComments"] = false; - * Value value; - * String errs; - * bool ok = parseFromStream(builder, std::cin, &value, &errs); - * \endcode - */ -class JSON_API CharReaderBuilder : public CharReader::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - * These are case-sensitive. - * Available settings (case-sensitive): - * - `"collectComments": false or true` - * - true to collect comment and allow writing them back during - * serialization, false to discard comments. This parameter is ignored - * if allowComments is false. - * - `"allowComments": false or true` - * - true if comments are allowed. - * - `"allowTrailingCommas": false or true` - * - true if trailing commas in objects and arrays are allowed. - * - `"strictRoot": false or true` - * - true if root must be either an array or an object value - * - `"allowDroppedNullPlaceholders": false or true` - * - true if dropped null placeholders are allowed. (See - * StreamWriterBuilder.) - * - `"allowNumericKeys": false or true` - * - true if numeric object keys are allowed. - * - `"allowSingleQuotes": false or true` - * - true if '' are allowed for strings (both keys and values) - * - `"stackLimit": integer` - * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an - * exception. - * - This is a security issue (seg-faults caused by deeply nested JSON), so - * the default is low. - * - `"failIfExtra": false or true` - * - If true, `parse()` returns false when extra non-whitespace trails the - * JSON value in the input string. - * - `"rejectDupKeys": false or true` - * - If true, `parse()` returns false when a key is duplicated within an - * object. - * - `"allowSpecialFloats": false or true` - * - If true, special float values (NaNs and infinities) are allowed and - * their values are lossfree restorable. - * - `"skipBom": false or true` - * - If true, if the input starts with the Unicode byte order mark (BOM), - * it is skipped. - * - * You can examine 'settings_` yourself to see the defaults. You can also - * write and read them just like any JSON Value. - * \sa setDefaults() - */ - Json::Value settings_; - - CharReaderBuilder(); - ~CharReaderBuilder() override; - - CharReader* newCharReader() const override; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - - /** A simple way to update a specific setting. - */ - Value& operator[](const String& key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults - */ - static void setDefaults(Json::Value* settings); - /** Same as old Features::strictMode(). - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode - */ - static void strictMode(Json::Value* settings); -}; - -/** Consume entire stream and use its begin/end. - * Someday we might have a real StreamReader, but for now this - * is convenient. - */ -bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root, - String* errs); - -/** \brief Read from 'sin' into 'root'. - * - * Always keep comments from the input JSON. - * - * This can be used to read a file into a particular sub-object. - * For example: - * \code - * Json::Value root; - * cin >> root["dir"]["file"]; - * cout << root; - * \endcode - * Result: - * \verbatim - * { - * "dir": { - * "file": { - * // The input stream JSON would be nested here. - * } - * } - * } - * \endverbatim - * \throw std::exception on parse error. - * \see Json::operator<<() - */ -JSON_API IStream& operator>>(IStream&, Value&); - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_READER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/reader.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_WRITER_H_INCLUDED -#define JSON_WRITER_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include "value.h" -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include - -// Disable warning C4251: : needs to have dll-interface to -// be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4251) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#pragma pack(push) -#pragma pack() - -namespace Json { - -class Value; - -/** - * - * Usage: - * \code - * using namespace Json; - * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) - * { std::unique_ptr const writer( factory.newStreamWriter()); - * writer->write(value, &std::cout); - * std::cout << std::endl; // add lf and flush - * } - * \endcode - */ -class JSON_API StreamWriter { -protected: - OStream* sout_; // not owned; will not delete -public: - StreamWriter(); - virtual ~StreamWriter(); - /** Write Value into document as configured in sub-class. - * Do not take ownership of sout, but maintain a reference during function. - * \pre sout != NULL - * \return zero on success (For now, we always return zero, so check the - * stream instead.) \throw std::exception possibly, depending on - * configuration - */ - virtual int write(Value const& root, OStream* sout) = 0; - - /** \brief A simple abstract factory. - */ - class JSON_API Factory { - public: - virtual ~Factory(); - /** \brief Allocate a CharReader via operator new(). - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - virtual StreamWriter* newStreamWriter() const = 0; - }; // Factory -}; // StreamWriter - -/** \brief Write into stringstream, then return string, for convenience. - * A StreamWriter will be created from the factory, used, and then deleted. - */ -String JSON_API writeString(StreamWriter::Factory const& factory, - Value const& root); - -/** \brief Build a StreamWriter implementation. - -* Usage: -* \code -* using namespace Json; -* Value value = ...; -* StreamWriterBuilder builder; -* builder["commentStyle"] = "None"; -* builder["indentation"] = " "; // or whatever you like -* std::unique_ptr writer( -* builder.newStreamWriter()); -* writer->write(value, &std::cout); -* std::cout << std::endl; // add lf and flush -* \endcode -*/ -class JSON_API StreamWriterBuilder : public StreamWriter::Factory { -public: - // Note: We use a Json::Value so that we can add data-members to this class - // without a major version bump. - /** Configuration of this builder. - * Available settings (case-sensitive): - * - "commentStyle": "None" or "All" - * - "indentation": "". - * - Setting this to an empty string also omits newline characters. - * - "enableYAMLCompatibility": false or true - * - slightly change the whitespace around colons - * - "dropNullPlaceholders": false or true - * - Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's JavaScript, it makes for smaller output and the - * browser can handle the output just fine. - * - "useSpecialFloats": false or true - * - If true, outputs non-finite floating point values in the following way: - * NaN values as "NaN", positive infinity as "Infinity", and negative - * infinity as "-Infinity". - * - "precision": int - * - Number of precision digits for formatting of real values. - * - "precisionType": "significant"(default) or "decimal" - * - Type of precision for formatting of real values. - * - "emitUTF8": false or true - * - If true, outputs raw UTF8 strings instead of escaping them. - - * You can examine 'settings_` yourself - * to see the defaults. You can also write and read them just like any - * JSON Value. - * \sa setDefaults() - */ - Json::Value settings_; - - StreamWriterBuilder(); - ~StreamWriterBuilder() override; - - /** - * \throw std::exception if something goes wrong (e.g. invalid settings) - */ - StreamWriter* newStreamWriter() const override; - - /** \return true if 'settings' are legal and consistent; - * otherwise, indicate bad settings via 'invalid'. - */ - bool validate(Json::Value* invalid) const; - /** A simple way to update a specific setting. - */ - Value& operator[](const String& key); - - /** Called by ctor, but you can use this to reset settings_. - * \pre 'settings' != NULL (but Json::null is fine) - * \remark Defaults: - * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults - */ - static void setDefaults(Json::Value* settings); -}; - -/** \brief Abstract class for writers. - * \deprecated Use StreamWriter. (And really, this is an implementation detail.) - */ -class JSON_API Writer { -public: - virtual ~Writer(); - - virtual String write(const Value& root) = 0; -}; - -/** \brief Outputs a Value in JSON format - *without formatting (not human friendly). - * - * The JSON document is written in a single line. It is not intended for 'human' - *consumption, - * but may be useful to support feature such as RPC where bandwidth is limited. - * \sa Reader, Value - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSON_API FastWriter - : public Writer { -public: - FastWriter(); - ~FastWriter() override = default; - - void enableYAMLCompatibility(); - - /** \brief Drop the "null" string from the writer's output for nullValues. - * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's JavaScript, it makes for smaller output and the - * browser can handle the output just fine. - */ - void dropNullPlaceholders(); - - void omitEndingLineFeed(); - -public: // overridden from Writer - String write(const Value& root) override; - -private: - void writeValue(const Value& value); - - String document_; - bool yamlCompatibilityEnabled_{false}; - bool dropNullPlaceholders_{false}; - bool omitEndingLineFeed_{false}; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -/** \brief Writes a Value in JSON format in a - *human friendly way. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - *line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - *types, - * and all the values fit on one lines, then print the array on a single - *line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputted according to their - *#CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSON_API - StyledWriter : public Writer { -public: - StyledWriter(); - ~StyledWriter() override = default; - -public: // overridden from Writer - /** \brief Serialize a Value in JSON format. - * \param root Value to serialize. - * \return String containing the JSON document that represents the root value. - */ - String write(const Value& root) override; - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultilineArray(const Value& value); - void pushValue(const String& value); - void writeIndent(); - void writeWithIndent(const String& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - static bool hasCommentForValue(const Value& value); - static String normalizeEOL(const String& text); - - using ChildValues = std::vector; - - ChildValues childValues_; - String document_; - String indentString_; - unsigned int rightMargin_{74}; - unsigned int indentSize_{3}; - bool addChildValues_{false}; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -/** \brief Writes a Value in JSON format in a - human friendly way, - to a stream rather than to a string. - * - * The rules for line break and indent are as follow: - * - Object value: - * - if empty then print {} without indent and line break - * - if not empty the print '{', line break & indent, print one value per - line - * and then unindent and line break and print '}'. - * - Array value: - * - if empty then print [] without indent and line break - * - if the array contains no object value, empty array or some other value - types, - * and all the values fit on one lines, then print the array on a single - line. - * - otherwise, it the values do not fit on one line, or the array contains - * object or non empty array, then print one value per line. - * - * If the Value have comments then they are outputted according to their - #CommentPlacement. - * - * \sa Reader, Value, Value::setComment() - * \deprecated Use StreamWriterBuilder. - */ -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4996) // Deriving from deprecated class -#endif -class JSON_API - StyledStreamWriter { -public: - /** - * \param indentation Each level will be indented by this amount extra. - */ - StyledStreamWriter(String indentation = "\t"); - ~StyledStreamWriter() = default; - -public: - /** \brief Serialize a Value in JSON format. - * \param out Stream to write to. (Can be ostringstream, e.g.) - * \param root Value to serialize. - * \note There is no point in deriving from Writer, since write() should not - * return a value. - */ - void write(OStream& out, const Value& root); - -private: - void writeValue(const Value& value); - void writeArrayValue(const Value& value); - bool isMultilineArray(const Value& value); - void pushValue(const String& value); - void writeIndent(); - void writeWithIndent(const String& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(const Value& root); - void writeCommentAfterValueOnSameLine(const Value& root); - static bool hasCommentForValue(const Value& value); - static String normalizeEOL(const String& text); - - using ChildValues = std::vector; - - ChildValues childValues_; - OStream* document_; - String indentString_; - unsigned int rightMargin_{74}; - String indentation_; - bool addChildValues_ : 1; - bool indented_ : 1; -}; -#if defined(_MSC_VER) -#pragma warning(pop) -#endif - -#if defined(JSON_HAS_INT64) -String JSON_API valueToString(Int value); -String JSON_API valueToString(UInt value); -#endif // if defined(JSON_HAS_INT64) -String JSON_API valueToString(LargestInt value); -String JSON_API valueToString(LargestUInt value); -String JSON_API valueToString( - double value, unsigned int precision = Value::defaultRealPrecision, - PrecisionType precisionType = PrecisionType::significantDigits); -String JSON_API valueToString(bool value); -String JSON_API valueToQuotedString(const char* value); - -/// \brief Output using the StyledStreamWriter. -/// \see Json::operator>>() -JSON_API OStream& operator<<(OStream&, const Value& root); - -} // namespace Json - -#pragma pack(pop) - -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#pragma warning(pop) -#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) - -#endif // JSON_WRITER_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/writer.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef JSON_ASSERTIONS_H_INCLUDED -#define JSON_ASSERTIONS_H_INCLUDED - -#include -#include - -#if !defined(JSON_IS_AMALGAMATION) -#include "config.h" -#endif // if !defined(JSON_IS_AMALGAMATION) - -/** It should not be possible for a maliciously designed file to - * cause an abort() or seg-fault, so these macros are used only - * for pre-condition violations and internal logic errors. - */ -#if JSON_USE_EXCEPTION - -// @todo <= add detail about condition in exception -#define JSON_ASSERT(condition) \ - do { \ - if (!(condition)) { \ - Json::throwLogicError("assert json failed"); \ - } \ - } while (0) - -#define JSON_FAIL_MESSAGE(message) \ - do { \ - OStringStream oss; \ - oss << message; \ - Json::throwLogicError(oss.str()); \ - abort(); \ - } while (0) - -#else // JSON_USE_EXCEPTION - -#define JSON_ASSERT(condition) assert(condition) - -// The call to assert() will show the failure message in debug builds. In -// release builds we abort, for a core-dump or debugger. -#define JSON_FAIL_MESSAGE(message) \ - { \ - OStringStream oss; \ - oss << message; \ - assert(false && oss.str().c_str()); \ - abort(); \ - } - -#endif - -#define JSON_ASSERT_MESSAGE(condition, message) \ - do { \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message); \ - } \ - } while (0) - -#endif // JSON_ASSERTIONS_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: include/json/assertions.h -// ////////////////////////////////////////////////////////////////////// - - - - - -#endif //ifndef JSON_AMALGAMATED_H_INCLUDED diff --git a/src/communication/pub_gps/include/pub_gps/pub_gps_node.hpp b/src/communication/pub_gps/include/pub_gps/pub_gps_node.hpp deleted file mode 100644 index c355994..0000000 --- a/src/communication/pub_gps/include/pub_gps/pub_gps_node.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __PUB_GPS_NODE_H__ -#define __PUB_GPS_NODE_H__ - -struct GPS -{ - double lng; // 经度 - double lat; // 维度 - float course; // 航向角 范围[0°, 360°],0°为正北方向,精度:0.1 - int mode; // 差分状态(定位)0:未定位 1:单点解 2:浮点解 3:固定解 -}; - -extern GPS gps_mes; - -#endif \ No newline at end of file diff --git a/src/communication/pub_gps/lib/libpaho-mqtt3c-static.a b/src/communication/pub_gps/lib/libpaho-mqtt3c-static.a deleted file mode 100644 index cbfe668..0000000 Binary files a/src/communication/pub_gps/lib/libpaho-mqtt3c-static.a and /dev/null differ diff --git a/src/communication/pub_gps/lib/libpaho-mqtt3c.a b/src/communication/pub_gps/lib/libpaho-mqtt3c.a deleted file mode 100644 index 9f7e1d5..0000000 Binary files a/src/communication/pub_gps/lib/libpaho-mqtt3c.a and /dev/null differ diff --git a/src/communication/pub_gps/package.xml b/src/communication/pub_gps/package.xml deleted file mode 100644 index 68460d8..0000000 --- a/src/communication/pub_gps/package.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - pub_gps - 0.0.0 - TODO: Package description - zxwl - TODO: License declaration - - ament_cmake - - rclcpp - std_msgs - sweeper_interfaces - - ament_lint_auto - ament_lint_common - - - ament_cmake - - \ No newline at end of file diff --git a/src/communication/pub_gps/src/jsoncpp.cpp b/src/communication/pub_gps/src/jsoncpp.cpp deleted file mode 100644 index 89b7bc0..0000000 --- a/src/communication/pub_gps/src/jsoncpp.cpp +++ /dev/null @@ -1,5342 +0,0 @@ -/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/). -/// It is intended to be used with #include "json/json.h" - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - -/* -The JsonCpp library's source code, including accompanying documentation, -tests and demonstration applications, are licensed under the following -conditions... - -Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all -jurisdictions which recognize such a disclaimer. In such jurisdictions, -this software is released into the Public Domain. - -In jurisdictions which do not recognize Public Domain property (e.g. Germany as of -2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and -The JsonCpp Authors, and is released under the terms of the MIT License (see below). - -In jurisdictions which recognize Public Domain property, the user of this -software may choose to accept it either as 1) Public Domain, 2) under the -conditions of the MIT License (see below), or 3) under the terms of dual -Public Domain/MIT License conditions described here, as they choose. - -The MIT License is about as close to Public Domain as a license can get, and is -described in clear, concise terms at: - - http://en.wikipedia.org/wiki/MIT_License - -The full text of the MIT License follows: - -======================================================================== -Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS -BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -======================================================================== -(END LICENSE TEXT) - -The MIT license is compatible with both the GPL and commercial -software, affording one all of the rights of Public Domain with the -minor nuisance of being required to keep the above copyright notice -and license text in the source code. Note also that by accepting the -Public Domain "license" you can re-license your copy using whatever -license you like. - -*/ - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: LICENSE -// ////////////////////////////////////////////////////////////////////// - - - - - - -#include "json.h" - -#ifndef JSON_IS_AMALGAMATION -#error "Compile with -I PATH_TO_JSON_DIRECTORY" -#endif - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED -#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -#if !defined(JSON_IS_AMALGAMATION) -#include -#endif - -// Also support old flag NO_LOCALE_SUPPORT -#ifdef NO_LOCALE_SUPPORT -#define JSONCPP_NO_LOCALE_SUPPORT -#endif - -#ifndef JSONCPP_NO_LOCALE_SUPPORT -#include -#endif - -/* This header provides common string manipulation support, such as UTF-8, - * portable conversion from/to string... - * - * It is an internal header that must not be exposed. - */ - -namespace Json { -static inline char getDecimalPoint() { -#ifdef JSONCPP_NO_LOCALE_SUPPORT - return '\0'; -#else - struct lconv* lc = localeconv(); - return lc ? *(lc->decimal_point) : '\0'; -#endif -} - -/// Converts a unicode code-point to UTF-8. -static inline String codePointToUTF8(unsigned int cp) { - String result; - - // based on description from http://en.wikipedia.org/wiki/UTF-8 - - if (cp <= 0x7f) { - result.resize(1); - result[0] = static_cast(cp); - } else if (cp <= 0x7FF) { - result.resize(2); - result[1] = static_cast(0x80 | (0x3f & cp)); - result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); - } else if (cp <= 0xFFFF) { - result.resize(3); - result[2] = static_cast(0x80 | (0x3f & cp)); - result[1] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[0] = static_cast(0xE0 | (0xf & (cp >> 12))); - } else if (cp <= 0x10FFFF) { - result.resize(4); - result[3] = static_cast(0x80 | (0x3f & cp)); - result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); - result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); - result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); - } - - return result; -} - -enum { - /// Constant that specify the size of the buffer that must be passed to - /// uintToString. - uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 -}; - -// Defines a char buffer for use with uintToString(). -using UIntToStringBuffer = char[uintToStringBufferSize]; - -/** Converts an unsigned integer to string. - * @param value Unsigned integer to convert to string - * @param current Input/Output string buffer. - * Must have at least uintToStringBufferSize chars free. - */ -static inline void uintToString(LargestUInt value, char*& current) { - *--current = 0; - do { - *--current = static_cast(value % 10U + static_cast('0')); - value /= 10; - } while (value != 0); -} - -/** Change ',' to '.' everywhere in buffer. - * - * We had a sophisticated way, but it did not work in WinCE. - * @see https://github.com/open-source-parsers/jsoncpp/pull/9 - */ -template Iter fixNumericLocale(Iter begin, Iter end) { - for (; begin != end; ++begin) { - if (*begin == ',') { - *begin = '.'; - } - } - return begin; -} - -template void fixNumericLocaleInput(Iter begin, Iter end) { - char decimalPoint = getDecimalPoint(); - if (decimalPoint == '\0' || decimalPoint == '.') { - return; - } - for (; begin != end; ++begin) { - if (*begin == '.') { - *begin = decimalPoint; - } - } -} - -/** - * Return iterator that would be the new end of the range [begin,end), if we - * were to delete zeros in the end of string, but not the last zero before '.'. - */ -template -Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) { - for (; begin != end; --end) { - if (*(end - 1) != '0') { - return end; - } - // Don't delete the last zero before the decimal point. - if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') { - if (precision) { - return end; - } - return end - 2; - } - } - return end; -} - -} // namespace Json - -#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_tool.h -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors -// Copyright (C) 2016 InfoTeCS JSC. All rights reserved. -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include "json_tool.h" -#include -#include -#include -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#if __cplusplus >= 201103L - -#if !defined(sscanf) -#define sscanf std::sscanf -#endif - -#endif //__cplusplus - -#if defined(_MSC_VER) -#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) -#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 -#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES -#endif //_MSC_VER - -#if defined(_MSC_VER) -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile -// time to change the stack limit -#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) -#define JSONCPP_DEPRECATED_STACK_LIMIT 1000 -#endif - -static size_t const stackLimit_g = - JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() - -namespace Json { - -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -using CharReaderPtr = std::unique_ptr; -#else -using CharReaderPtr = std::auto_ptr; -#endif - -// Implementation of class Features -// //////////////////////////////// - -Features::Features() = default; - -Features Features::all() { return {}; } - -Features Features::strictMode() { - Features features; - features.allowComments_ = false; - features.strictRoot_ = true; - features.allowDroppedNullPlaceholders_ = false; - features.allowNumericKeys_ = false; - return features; -} - -// Implementation of class Reader -// //////////////////////////////// - -bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { - return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); -} - -// Class Reader -// ////////////////////////////////////////////////////////////////// - -Reader::Reader() : features_(Features::all()) {} - -Reader::Reader(const Features& features) : features_(features) {} - -bool Reader::parse(const std::string& document, Value& root, - bool collectComments) { - document_.assign(document.begin(), document.end()); - const char* begin = document_.c_str(); - const char* end = begin + document_.length(); - return parse(begin, end, root, collectComments); -} - -bool Reader::parse(std::istream& is, Value& root, bool collectComments) { - // std::istream_iterator begin(is); - // std::istream_iterator end; - // Those would allow streamed input from a file, if parse() were a - // template function. - - // Since String is reference-counted, this at least does not - // create an extra copy. - String doc(std::istreambuf_iterator(is), {}); - return parse(doc.data(), doc.data() + doc.size(), root, collectComments); -} - -bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = nullptr; - lastValue_ = nullptr; - commentsBefore_.clear(); - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - bool successful = readValue(); - Token token; - skipCommentTokens(token); - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool Reader::readValue() { - // readValue() may call itself only if it calls readObject() or ReadArray(). - // These methods execute nodes_.push() just before and nodes_.pop)() just - // after calling readValue(). parse() executes one nodes_.push(), so > instead - // of >=. - if (nodes_.size() > stackLimit_g) - throwRuntimeError("Exceeded stackLimit in readValue()."); - - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_.clear(); - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenFalse: { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNull: { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // Else, fall through... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void Reader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool Reader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - token.type_ = tokenNumber; - readNumber(); - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return ok; -} - -void Reader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -bool Reader::match(const Char* pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool Reader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); - bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') - successful = readCppStyleComment(); - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { - String normalized; - normalized.reserve(static_cast(end - begin)); - Reader::Location current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') { - if (current != end && *current == '\n') - // convert dos EOL - ++current; - // convert Mac EOL - normalized += '\n'; - } else { - normalized += c; - } - } - return normalized; -} - -void Reader::addComment(Location begin, Location end, - CommentPlacement placement) { - assert(collectComments_); - const String& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != nullptr); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool Reader::readCStyleComment() { - while ((current_ + 1) < end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - } - return getNextChar() == '/'; -} - -bool Reader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -void Reader::readNumber() { - Location p = current_; - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : '\0'; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } -} - -bool Reader::readString() { - Char c = '\0'; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool Reader::readObject(Token& token) { - Token tokenName; - String name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object - return true; - name.clear(); - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover("Missing ':' after object member name", colon, - tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover("Missing ',' or '}' in object declaration", - comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover("Missing '}' or object member name", tokenName, - tokenObjectEnd); -} - -bool Reader::readArray(Token& token) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - skipSpaces(); - if (current_ != end_ && *current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } - int index = 0; - for (;;) { - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token currentToken; - // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } - bool badTokenType = (currentToken.type_ != tokenArraySeparator && - currentToken.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover("Missing ',' or ']' in array declaration", - currentToken, tokenArrayEnd); - } - if (currentToken.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool Reader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) - ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of - // them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - auto digit(static_cast(c - '0')); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - if (isNegative && value == maxIntegerValue) - decoded = Value::minLargestInt; - else if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) - decoded = Value::LargestInt(value); - else - decoded = value; - return true; -} - -bool Reader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - String buffer(token.start_, token.end_); - IStringStream is(buffer); - if (!(is >> value)) { - if (value == std::numeric_limits::max()) - value = std::numeric_limits::infinity(); - else if (value == std::numeric_limits::lowest()) - value = -std::numeric_limits::infinity(); - else if (!std::isinf(value)) - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); - } - decoded = value; - return true; -} - -bool Reader::decodeString(Token& token) { - String decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool Reader::decodeString(Token& token, String& decoded) { - decoded.reserve(static_cast(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool Reader::decodeUnicodeCodePoint(Token& token, Location& current, - Location end, unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); - if (*(current++) == '\\' && *(current++) == 'u') { - unsigned int surrogatePair; - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); - } - return true; -} - -bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, - unsigned int& ret_unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); - int unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); - } - ret_unicode = static_cast(unicode); - return true; -} - -bool Reader::addError(const String& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool Reader::recoverFromError(TokenType skipUntilToken) { - size_t const errorCount = errors_.size(); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool Reader::addErrorAndRecover(const String& message, Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& Reader::currentValue() { return *(nodes_.top()); } - -Reader::Char Reader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void Reader::getLocationLineAndColumn(Location location, int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -String Reader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; - jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); - return buffer; -} - -// Deprecated. Preserved for backward compatibility -String Reader::getFormatedErrorMessages() const { - return getFormattedErrorMessages(); -} - -String Reader::getFormattedErrorMessages() const { - String formattedMessage; - for (const auto& error : errors_) { - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector Reader::getStructuredErrors() const { - std::vector allErrors; - for (const auto& error : errors_) { - Reader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -bool Reader::pushError(const Value& value, const String& message) { - ptrdiff_t const length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = nullptr; - errors_.push_back(info); - return true; -} - -bool Reader::pushError(const Value& value, const String& message, - const Value& extra) { - ptrdiff_t const length = end_ - begin_; - if (value.getOffsetStart() > length || value.getOffsetLimit() > length || - extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool Reader::good() const { return errors_.empty(); } - -// Originally copied from the Features class (now deprecated), used internally -// for features implementation. -class OurFeatures { -public: - static OurFeatures all(); - bool allowComments_; - bool allowTrailingCommas_; - bool strictRoot_; - bool allowDroppedNullPlaceholders_; - bool allowNumericKeys_; - bool allowSingleQuotes_; - bool failIfExtra_; - bool rejectDupKeys_; - bool allowSpecialFloats_; - bool skipBom_; - size_t stackLimit_; -}; // OurFeatures - -OurFeatures OurFeatures::all() { return {}; } - -// Implementation of class Reader -// //////////////////////////////// - -// Originally copied from the Reader class (now deprecated), used internally -// for implementing JSON reading. -class OurReader { -public: - using Char = char; - using Location = const Char*; - struct StructuredError { - ptrdiff_t offset_start; - ptrdiff_t offset_limit; - String message; - }; - - explicit OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments = true); - String getFormattedErrorMessages() const; - std::vector getStructuredErrors() const; - -private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl - - enum TokenType { - tokenEndOfStream = 0, - tokenObjectBegin, - tokenObjectEnd, - tokenArrayBegin, - tokenArrayEnd, - tokenString, - tokenNumber, - tokenTrue, - tokenFalse, - tokenNull, - tokenNaN, - tokenPosInf, - tokenNegInf, - tokenArraySeparator, - tokenMemberSeparator, - tokenComment, - tokenError - }; - - class Token { - public: - TokenType type_; - Location start_; - Location end_; - }; - - class ErrorInfo { - public: - Token token_; - String message_; - Location extra_; - }; - - using Errors = std::deque; - - bool readToken(Token& token); - void skipSpaces(); - void skipBom(bool skipBom); - bool match(const Char* pattern, int patternLength); - bool readComment(); - bool readCStyleComment(bool* containsNewLineResult); - bool readCppStyleComment(); - bool readString(); - bool readStringSingleQuote(); - bool readNumber(bool checkInf); - bool readValue(); - bool readObject(Token& token); - bool readArray(Token& token); - bool decodeNumber(Token& token); - bool decodeNumber(Token& token, Value& decoded); - bool decodeString(Token& token); - bool decodeString(Token& token, String& decoded); - bool decodeDouble(Token& token); - bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, - unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, unsigned int& unicode); - bool addError(const String& message, Token& token, Location extra = nullptr); - bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const String& message, Token& token, - TokenType skipUntilToken); - void skipUntilSpace(); - Value& currentValue(); - Char getNextChar(); - void getLocationLineAndColumn(Location location, int& line, - int& column) const; - String getLocationLineAndColumn(Location location) const; - void addComment(Location begin, Location end, CommentPlacement placement); - void skipCommentTokens(Token& token); - - static String normalizeEOL(Location begin, Location end); - static bool containsNewLine(Location begin, Location end); - - using Nodes = std::stack; - - Nodes nodes_{}; - Errors errors_{}; - String document_{}; - Location begin_ = nullptr; - Location end_ = nullptr; - Location current_ = nullptr; - Location lastValueEnd_ = nullptr; - Value* lastValue_ = nullptr; - bool lastValueHasAComment_ = false; - String commentsBefore_{}; - - OurFeatures const features_; - bool collectComments_ = false; -}; // OurReader - -// complete copy of Read impl, for OurReader - -bool OurReader::containsNewLine(OurReader::Location begin, - OurReader::Location end) { - return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); -} - -OurReader::OurReader(OurFeatures const& features) : features_(features) {} - -bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, - bool collectComments) { - if (!features_.allowComments_) { - collectComments = false; - } - - begin_ = beginDoc; - end_ = endDoc; - collectComments_ = collectComments; - current_ = begin_; - lastValueEnd_ = nullptr; - lastValue_ = nullptr; - commentsBefore_.clear(); - errors_.clear(); - while (!nodes_.empty()) - nodes_.pop(); - nodes_.push(&root); - - // skip byte order mark if it exists at the beginning of the UTF-8 text. - skipBom(features_.skipBom_); - bool successful = readValue(); - nodes_.pop(); - Token token; - skipCommentTokens(token); - if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) { - addError("Extra non-whitespace after JSON value.", token); - return false; - } - if (collectComments_ && !commentsBefore_.empty()) - root.setComment(commentsBefore_, commentAfter); - if (features_.strictRoot_) { - if (!root.isArray() && !root.isObject()) { - // Set error location to start of doc, ideally should be first token found - // in doc - token.type_ = tokenError; - token.start_ = beginDoc; - token.end_ = endDoc; - addError( - "A valid JSON document must be either an array or an object value.", - token); - return false; - } - } - return successful; -} - -bool OurReader::readValue() { - // To preserve the old behaviour we cast size_t to int. - if (nodes_.size() > features_.stackLimit_) - throwRuntimeError("Exceeded stackLimit in readValue()."); - Token token; - skipCommentTokens(token); - bool successful = true; - - if (collectComments_ && !commentsBefore_.empty()) { - currentValue().setComment(commentsBefore_, commentBefore); - commentsBefore_.clear(); - } - - switch (token.type_) { - case tokenObjectBegin: - successful = readObject(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenArrayBegin: - successful = readArray(token); - currentValue().setOffsetLimit(current_ - begin_); - break; - case tokenNumber: - successful = decodeNumber(token); - break; - case tokenString: - successful = decodeString(token); - break; - case tokenTrue: { - Value v(true); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenFalse: { - Value v(false); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNull: { - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNaN: { - Value v(std::numeric_limits::quiet_NaN()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenPosInf: { - Value v(std::numeric_limits::infinity()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenNegInf: { - Value v(-std::numeric_limits::infinity()); - currentValue().swapPayload(v); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - } break; - case tokenArraySeparator: - case tokenObjectEnd: - case tokenArrayEnd: - if (features_.allowDroppedNullPlaceholders_) { - // "Un-read" the current token and mark the current value as a null - // token. - current_--; - Value v; - currentValue().swapPayload(v); - currentValue().setOffsetStart(current_ - begin_ - 1); - currentValue().setOffsetLimit(current_ - begin_); - break; - } // else, fall through ... - default: - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return addError("Syntax error: value, object or array expected.", token); - } - - if (collectComments_) { - lastValueEnd_ = current_; - lastValueHasAComment_ = false; - lastValue_ = ¤tValue(); - } - - return successful; -} - -void OurReader::skipCommentTokens(Token& token) { - if (features_.allowComments_) { - do { - readToken(token); - } while (token.type_ == tokenComment); - } else { - readToken(token); - } -} - -bool OurReader::readToken(Token& token) { - skipSpaces(); - token.start_ = current_; - Char c = getNextChar(); - bool ok = true; - switch (c) { - case '{': - token.type_ = tokenObjectBegin; - break; - case '}': - token.type_ = tokenObjectEnd; - break; - case '[': - token.type_ = tokenArrayBegin; - break; - case ']': - token.type_ = tokenArrayEnd; - break; - case '"': - token.type_ = tokenString; - ok = readString(); - break; - case '\'': - if (features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = readStringSingleQuote(); - } else { - // If we don't allow single quotes, this is a failure case. - ok = false; - } - break; - case '/': - token.type_ = tokenComment; - ok = readComment(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - token.type_ = tokenNumber; - readNumber(false); - break; - case '-': - if (readNumber(true)) { - token.type_ = tokenNumber; - } else { - token.type_ = tokenNegInf; - ok = features_.allowSpecialFloats_ && match("nfinity", 7); - } - break; - case '+': - if (readNumber(true)) { - token.type_ = tokenNumber; - } else { - token.type_ = tokenPosInf; - ok = features_.allowSpecialFloats_ && match("nfinity", 7); - } - break; - case 't': - token.type_ = tokenTrue; - ok = match("rue", 3); - break; - case 'f': - token.type_ = tokenFalse; - ok = match("alse", 4); - break; - case 'n': - token.type_ = tokenNull; - ok = match("ull", 3); - break; - case 'N': - if (features_.allowSpecialFloats_) { - token.type_ = tokenNaN; - ok = match("aN", 2); - } else { - ok = false; - } - break; - case 'I': - if (features_.allowSpecialFloats_) { - token.type_ = tokenPosInf; - ok = match("nfinity", 7); - } else { - ok = false; - } - break; - case ',': - token.type_ = tokenArraySeparator; - break; - case ':': - token.type_ = tokenMemberSeparator; - break; - case 0: - token.type_ = tokenEndOfStream; - break; - default: - ok = false; - break; - } - if (!ok) - token.type_ = tokenError; - token.end_ = current_; - return ok; -} - -void OurReader::skipSpaces() { - while (current_ != end_) { - Char c = *current_; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - ++current_; - else - break; - } -} - -void OurReader::skipBom(bool skipBom) { - // The default behavior is to skip BOM. - if (skipBom) { - if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) { - begin_ += 3; - current_ = begin_; - } - } -} - -bool OurReader::match(const Char* pattern, int patternLength) { - if (end_ - current_ < patternLength) - return false; - int index = patternLength; - while (index--) - if (current_[index] != pattern[index]) - return false; - current_ += patternLength; - return true; -} - -bool OurReader::readComment() { - const Location commentBegin = current_ - 1; - const Char c = getNextChar(); - bool successful = false; - bool cStyleWithEmbeddedNewline = false; - - const bool isCStyleComment = (c == '*'); - const bool isCppStyleComment = (c == '/'); - if (isCStyleComment) { - successful = readCStyleComment(&cStyleWithEmbeddedNewline); - } else if (isCppStyleComment) { - successful = readCppStyleComment(); - } - - if (!successful) - return false; - - if (collectComments_) { - CommentPlacement placement = commentBefore; - - if (!lastValueHasAComment_) { - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (isCppStyleComment || !cStyleWithEmbeddedNewline) { - placement = commentAfterOnSameLine; - lastValueHasAComment_ = true; - } - } - } - - addComment(commentBegin, current_, placement); - } - return true; -} - -String OurReader::normalizeEOL(OurReader::Location begin, - OurReader::Location end) { - String normalized; - normalized.reserve(static_cast(end - begin)); - OurReader::Location current = begin; - while (current != end) { - char c = *current++; - if (c == '\r') { - if (current != end && *current == '\n') - // convert dos EOL - ++current; - // convert Mac EOL - normalized += '\n'; - } else { - normalized += c; - } - } - return normalized; -} - -void OurReader::addComment(Location begin, Location end, - CommentPlacement placement) { - assert(collectComments_); - const String& normalized = normalizeEOL(begin, end); - if (placement == commentAfterOnSameLine) { - assert(lastValue_ != nullptr); - lastValue_->setComment(normalized, placement); - } else { - commentsBefore_ += normalized; - } -} - -bool OurReader::readCStyleComment(bool* containsNewLineResult) { - *containsNewLineResult = false; - - while ((current_ + 1) < end_) { - Char c = getNextChar(); - if (c == '*' && *current_ == '/') - break; - if (c == '\n') - *containsNewLineResult = true; - } - - return getNextChar() == '/'; -} - -bool OurReader::readCppStyleComment() { - while (current_ != end_) { - Char c = getNextChar(); - if (c == '\n') - break; - if (c == '\r') { - // Consume DOS EOL. It will be normalized in addComment. - if (current_ != end_ && *current_ == '\n') - getNextChar(); - // Break on Moc OS 9 EOL. - break; - } - } - return true; -} - -bool OurReader::readNumber(bool checkInf) { - Location p = current_; - if (checkInf && p != end_ && *p == 'I') { - current_ = ++p; - return false; - } - char c = '0'; // stopgap for already consumed character - // integral part - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - // fractional part - if (c == '.') { - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - // exponential part - if (c == 'e' || c == 'E') { - c = (current_ = p) < end_ ? *p++ : '\0'; - if (c == '+' || c == '-') - c = (current_ = p) < end_ ? *p++ : '\0'; - while (c >= '0' && c <= '9') - c = (current_ = p) < end_ ? *p++ : '\0'; - } - return true; -} -bool OurReader::readString() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '"') - break; - } - return c == '"'; -} - -bool OurReader::readStringSingleQuote() { - Char c = 0; - while (current_ != end_) { - c = getNextChar(); - if (c == '\\') - getNextChar(); - else if (c == '\'') - break; - } - return c == '\''; -} - -bool OurReader::readObject(Token& token) { - Token tokenName; - String name; - Value init(objectValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - while (readToken(tokenName)) { - bool initialTokenOk = true; - while (tokenName.type_ == tokenComment && initialTokenOk) - initialTokenOk = readToken(tokenName); - if (!initialTokenOk) - break; - if (tokenName.type_ == tokenObjectEnd && - (name.empty() || - features_.allowTrailingCommas_)) // empty object or trailing comma - return true; - name.clear(); - if (tokenName.type_ == tokenString) { - if (!decodeString(tokenName, name)) - return recoverFromError(tokenObjectEnd); - } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { - Value numberName; - if (!decodeNumber(tokenName, numberName)) - return recoverFromError(tokenObjectEnd); - name = numberName.asString(); - } else { - break; - } - if (name.length() >= (1U << 30)) - throwRuntimeError("keylength >= 2^30"); - if (features_.rejectDupKeys_ && currentValue().isMember(name)) { - String msg = "Duplicate key: '" + name + "'"; - return addErrorAndRecover(msg, tokenName, tokenObjectEnd); - } - - Token colon; - if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover("Missing ':' after object member name", colon, - tokenObjectEnd); - } - Value& value = currentValue()[name]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenObjectEnd); - - Token comma; - if (!readToken(comma) || - (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && - comma.type_ != tokenComment)) { - return addErrorAndRecover("Missing ',' or '}' in object declaration", - comma, tokenObjectEnd); - } - bool finalizeTokenOk = true; - while (comma.type_ == tokenComment && finalizeTokenOk) - finalizeTokenOk = readToken(comma); - if (comma.type_ == tokenObjectEnd) - return true; - } - return addErrorAndRecover("Missing '}' or object member name", tokenName, - tokenObjectEnd); -} - -bool OurReader::readArray(Token& token) { - Value init(arrayValue); - currentValue().swapPayload(init); - currentValue().setOffsetStart(token.start_ - begin_); - int index = 0; - for (;;) { - skipSpaces(); - if (current_ != end_ && *current_ == ']' && - (index == 0 || - (features_.allowTrailingCommas_ && - !features_.allowDroppedNullPlaceholders_))) // empty array or trailing - // comma - { - Token endArray; - readToken(endArray); - return true; - } - Value& value = currentValue()[index++]; - nodes_.push(&value); - bool ok = readValue(); - nodes_.pop(); - if (!ok) // error already set - return recoverFromError(tokenArrayEnd); - - Token currentToken; - // Accept Comment after last item in the array. - ok = readToken(currentToken); - while (currentToken.type_ == tokenComment && ok) { - ok = readToken(currentToken); - } - bool badTokenType = (currentToken.type_ != tokenArraySeparator && - currentToken.type_ != tokenArrayEnd); - if (!ok || badTokenType) { - return addErrorAndRecover("Missing ',' or ']' in array declaration", - currentToken, tokenArrayEnd); - } - if (currentToken.type_ == tokenArrayEnd) - break; - } - return true; -} - -bool OurReader::decodeNumber(Token& token) { - Value decoded; - if (!decodeNumber(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeNumber(Token& token, Value& decoded) { - // Attempts to parse the number as an integer. If the number is - // larger than the maximum supported value of an integer then - // we decode the number as a double. - Location current = token.start_; - const bool isNegative = *current == '-'; - if (isNegative) { - ++current; - } - - // We assume we can represent the largest and smallest integer types as - // unsigned integers with separate sign. This is only true if they can fit - // into an unsigned integer. - static_assert(Value::maxLargestInt <= Value::maxLargestUInt, - "Int must be smaller than UInt"); - - // We need to convert minLargestInt into a positive number. The easiest way - // to do this conversion is to assume our "threshold" value of minLargestInt - // divided by 10 can fit in maxLargestInt when absolute valued. This should - // be a safe assumption. - static_assert(Value::minLargestInt <= -Value::maxLargestInt, - "The absolute value of minLargestInt must be greater than or " - "equal to maxLargestInt"); - static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, - "The absolute value of minLargestInt must be only 1 magnitude " - "larger than maxLargest Int"); - - static constexpr Value::LargestUInt positive_threshold = - Value::maxLargestUInt / 10; - static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10; - - // For the negative values, we have to be more careful. Since typically - // -Value::minLargestInt will cause an overflow, we first divide by 10 and - // then take the inverse. This assumes that minLargestInt is only a single - // power of 10 different in magnitude, which we check above. For the last - // digit, we take the modulus before negating for the same reason. - static constexpr auto negative_threshold = - Value::LargestUInt(-(Value::minLargestInt / 10)); - static constexpr auto negative_last_digit = - Value::UInt(-(Value::minLargestInt % 10)); - - const Value::LargestUInt threshold = - isNegative ? negative_threshold : positive_threshold; - const Value::UInt max_last_digit = - isNegative ? negative_last_digit : positive_last_digit; - - Value::LargestUInt value = 0; - while (current < token.end_) { - Char c = *current++; - if (c < '0' || c > '9') - return decodeDouble(token, decoded); - - const auto digit(static_cast(c - '0')); - if (value >= threshold) { - // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, meaning value == threshold, - // b) this is the last digit, or - // c) it's small enough to fit in that rounding delta, we're okay. - // Otherwise treat this number as a double to avoid overflow. - if (value > threshold || current != token.end_ || - digit > max_last_digit) { - return decodeDouble(token, decoded); - } - } - value = value * 10 + digit; - } - - if (isNegative) { - // We use the same magnitude assumption here, just in case. - const auto last_digit = static_cast(value % 10); - decoded = -Value::LargestInt(value / 10) * 10 - last_digit; - } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { - decoded = Value::LargestInt(value); - } else { - decoded = value; - } - - return true; -} - -bool OurReader::decodeDouble(Token& token) { - Value decoded; - if (!decodeDouble(token, decoded)) - return false; - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeDouble(Token& token, Value& decoded) { - double value = 0; - const String buffer(token.start_, token.end_); - IStringStream is(buffer); - if (!(is >> value)) { - if (value == std::numeric_limits::max()) - value = std::numeric_limits::infinity(); - else if (value == std::numeric_limits::lowest()) - value = -std::numeric_limits::infinity(); - else if (!std::isinf(value)) - return addError( - "'" + String(token.start_, token.end_) + "' is not a number.", token); - } - decoded = value; - return true; -} - -bool OurReader::decodeString(Token& token) { - String decoded_string; - if (!decodeString(token, decoded_string)) - return false; - Value decoded(decoded_string); - currentValue().swapPayload(decoded); - currentValue().setOffsetStart(token.start_ - begin_); - currentValue().setOffsetLimit(token.end_ - begin_); - return true; -} - -bool OurReader::decodeString(Token& token, String& decoded) { - decoded.reserve(static_cast(token.end_ - token.start_ - 2)); - Location current = token.start_ + 1; // skip '"' - Location end = token.end_ - 1; // do not include '"' - while (current != end) { - Char c = *current++; - if (c == '"') - break; - if (c == '\\') { - if (current == end) - return addError("Empty escape sequence in string", token, current); - Char escape = *current++; - switch (escape) { - case '"': - decoded += '"'; - break; - case '/': - decoded += '/'; - break; - case '\\': - decoded += '\\'; - break; - case 'b': - decoded += '\b'; - break; - case 'f': - decoded += '\f'; - break; - case 'n': - decoded += '\n'; - break; - case 'r': - decoded += '\r'; - break; - case 't': - decoded += '\t'; - break; - case 'u': { - unsigned int unicode; - if (!decodeUnicodeCodePoint(token, current, end, unicode)) - return false; - decoded += codePointToUTF8(unicode); - } break; - default: - return addError("Bad escape sequence in string", token, current); - } - } else { - decoded += c; - } - } - return true; -} - -bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current, - Location end, unsigned int& unicode) { - - if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) - return false; - if (unicode >= 0xD800 && unicode <= 0xDBFF) { - // surrogate pairs - if (end - current < 6) - return addError( - "additional six characters expected to parse unicode surrogate pair.", - token, current); - if (*(current++) == '\\' && *(current++) == 'u') { - unsigned int surrogatePair; - if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { - unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); - } else - return false; - } else - return addError("expecting another \\u token to begin the second half of " - "a unicode surrogate pair", - token, current); - } - return true; -} - -bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, - Location end, - unsigned int& ret_unicode) { - if (end - current < 4) - return addError( - "Bad unicode escape sequence in string: four digits expected.", token, - current); - int unicode = 0; - for (int index = 0; index < 4; ++index) { - Char c = *current++; - unicode *= 16; - if (c >= '0' && c <= '9') - unicode += c - '0'; - else if (c >= 'a' && c <= 'f') - unicode += c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - unicode += c - 'A' + 10; - else - return addError( - "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, current); - } - ret_unicode = static_cast(unicode); - return true; -} - -bool OurReader::addError(const String& message, Token& token, Location extra) { - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = extra; - errors_.push_back(info); - return false; -} - -bool OurReader::recoverFromError(TokenType skipUntilToken) { - size_t errorCount = errors_.size(); - Token skip; - for (;;) { - if (!readToken(skip)) - errors_.resize(errorCount); // discard errors caused by recovery - if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) - break; - } - errors_.resize(errorCount); - return false; -} - -bool OurReader::addErrorAndRecover(const String& message, Token& token, - TokenType skipUntilToken) { - addError(message, token); - return recoverFromError(skipUntilToken); -} - -Value& OurReader::currentValue() { return *(nodes_.top()); } - -OurReader::Char OurReader::getNextChar() { - if (current_ == end_) - return 0; - return *current_++; -} - -void OurReader::getLocationLineAndColumn(Location location, int& line, - int& column) const { - Location current = begin_; - Location lastLineStart = current; - line = 0; - while (current < location && current != end_) { - Char c = *current++; - if (c == '\r') { - if (*current == '\n') - ++current; - lastLineStart = current; - ++line; - } else if (c == '\n') { - lastLineStart = current; - ++line; - } - } - // column & line start at 1 - column = int(location - lastLineStart) + 1; - ++line; -} - -String OurReader::getLocationLineAndColumn(Location location) const { - int line, column; - getLocationLineAndColumn(location, line, column); - char buffer[18 + 16 + 16 + 1]; - jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); - return buffer; -} - -String OurReader::getFormattedErrorMessages() const { - String formattedMessage; - for (const auto& error : errors_) { - formattedMessage += - "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; - formattedMessage += " " + error.message_ + "\n"; - if (error.extra_) - formattedMessage += - "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; - } - return formattedMessage; -} - -std::vector OurReader::getStructuredErrors() const { - std::vector allErrors; - for (const auto& error : errors_) { - OurReader::StructuredError structured; - structured.offset_start = error.token_.start_ - begin_; - structured.offset_limit = error.token_.end_ - begin_; - structured.message = error.message_; - allErrors.push_back(structured); - } - return allErrors; -} - -class OurCharReader : public CharReader { - bool const collectComments_; - OurReader reader_; - -public: - OurCharReader(bool collectComments, OurFeatures const& features) - : collectComments_(collectComments), reader_(features) {} - bool parse(char const* beginDoc, char const* endDoc, Value* root, - String* errs) override { - bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); - if (errs) { - *errs = reader_.getFormattedErrorMessages(); - } - return ok; - } -}; - -CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } -CharReaderBuilder::~CharReaderBuilder() = default; -CharReader* CharReaderBuilder::newCharReader() const { - bool collectComments = settings_["collectComments"].asBool(); - OurFeatures features = OurFeatures::all(); - features.allowComments_ = settings_["allowComments"].asBool(); - features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool(); - features.strictRoot_ = settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = - settings_["allowDroppedNullPlaceholders"].asBool(); - features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); - features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); - - // Stack limit is always a size_t, so we get this as an unsigned int - // regardless of it we have 64-bit integer support enabled. - features.stackLimit_ = static_cast(settings_["stackLimit"].asUInt()); - features.failIfExtra_ = settings_["failIfExtra"].asBool(); - features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); - features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); - features.skipBom_ = settings_["skipBom"].asBool(); - return new OurCharReader(collectComments, features); -} - -bool CharReaderBuilder::validate(Json::Value* invalid) const { - static const auto& valid_keys = *new std::set{ - "collectComments", - "allowComments", - "allowTrailingCommas", - "strictRoot", - "allowDroppedNullPlaceholders", - "allowNumericKeys", - "allowSingleQuotes", - "stackLimit", - "failIfExtra", - "rejectDupKeys", - "allowSpecialFloats", - "skipBom", - }; - for (auto si = settings_.begin(); si != settings_.end(); ++si) { - auto key = si.name(); - if (valid_keys.count(key)) - continue; - if (invalid) - (*invalid)[key] = *si; - else - return false; - } - return invalid ? invalid->empty() : true; -} - -Value& CharReaderBuilder::operator[](const String& key) { - return settings_[key]; -} -// static -void CharReaderBuilder::strictMode(Json::Value* settings) { - //! [CharReaderBuilderStrictMode] - (*settings)["allowComments"] = false; - (*settings)["allowTrailingCommas"] = false; - (*settings)["strictRoot"] = true; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["stackLimit"] = 1000; - (*settings)["failIfExtra"] = true; - (*settings)["rejectDupKeys"] = true; - (*settings)["allowSpecialFloats"] = false; - (*settings)["skipBom"] = true; - //! [CharReaderBuilderStrictMode] -} -// static -void CharReaderBuilder::setDefaults(Json::Value* settings) { - //! [CharReaderBuilderDefaults] - (*settings)["collectComments"] = true; - (*settings)["allowComments"] = true; - (*settings)["allowTrailingCommas"] = true; - (*settings)["strictRoot"] = false; - (*settings)["allowDroppedNullPlaceholders"] = false; - (*settings)["allowNumericKeys"] = false; - (*settings)["allowSingleQuotes"] = false; - (*settings)["stackLimit"] = 1000; - (*settings)["failIfExtra"] = false; - (*settings)["rejectDupKeys"] = false; - (*settings)["allowSpecialFloats"] = false; - (*settings)["skipBom"] = true; - //! [CharReaderBuilderDefaults] -} - -////////////////////////////////// -// global functions - -bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root, - String* errs) { - OStringStream ssin; - ssin << sin.rdbuf(); - String doc = ssin.str(); - char const* begin = doc.data(); - char const* end = begin + doc.size(); - // Note that we do not actually need a null-terminator. - CharReaderPtr const reader(fact.newCharReader()); - return reader->parse(begin, end, root, errs); -} - -IStream& operator>>(IStream& sin, Value& root) { - CharReaderBuilder b; - String errs; - bool ok = parseFromStream(b, sin, &root, &errs); - if (!ok) { - throwRuntimeError(errs); - } - return sin; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_reader.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -// included by json_value.cpp - -namespace Json { - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIteratorBase -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIteratorBase::ValueIteratorBase() : current_() {} - -ValueIteratorBase::ValueIteratorBase( - const Value::ObjectValues::iterator& current) - : current_(current), isNull_(false) {} - -Value& ValueIteratorBase::deref() { return current_->second; } -const Value& ValueIteratorBase::deref() const { return current_->second; } - -void ValueIteratorBase::increment() { ++current_; } - -void ValueIteratorBase::decrement() { --current_; } - -ValueIteratorBase::difference_type -ValueIteratorBase::computeDistance(const SelfType& other) const { - // Iterator for null value are initialized using the default - // constructor, which initialize current_ to the default - // std::map::iterator. As begin() and end() are two instance - // of the default std::map::iterator, they can not be compared. - // To allow this, we handle this comparison specifically. - if (isNull_ && other.isNull_) { - return 0; - } - - // Usage of std::distance is not portable (does not compile with Sun Studio 12 - // RogueWave STL, - // which is the one used by default). - // Using a portable hand-made version for non random iterator instead: - // return difference_type( std::distance( current_, other.current_ ) ); - difference_type myDistance = 0; - for (Value::ObjectValues::iterator it = current_; it != other.current_; - ++it) { - ++myDistance; - } - return myDistance; -} - -bool ValueIteratorBase::isEqual(const SelfType& other) const { - if (isNull_) { - return other.isNull_; - } - return current_ == other.current_; -} - -void ValueIteratorBase::copy(const SelfType& other) { - current_ = other.current_; - isNull_ = other.isNull_; -} - -Value ValueIteratorBase::key() const { - const Value::CZString czstring = (*current_).first; - if (czstring.data()) { - if (czstring.isStaticString()) - return Value(StaticString(czstring.data())); - return Value(czstring.data(), czstring.data() + czstring.length()); - } - return Value(czstring.index()); -} - -UInt ValueIteratorBase::index() const { - const Value::CZString czstring = (*current_).first; - if (!czstring.data()) - return czstring.index(); - return Value::UInt(-1); -} - -String ValueIteratorBase::name() const { - char const* keey; - char const* end; - keey = memberName(&end); - if (!keey) - return String(); - return String(keey, end); -} - -char const* ValueIteratorBase::memberName() const { - const char* cname = (*current_).first.data(); - return cname ? cname : ""; -} - -char const* ValueIteratorBase::memberName(char const** end) const { - const char* cname = (*current_).first.data(); - if (!cname) { - *end = nullptr; - return nullptr; - } - *end = cname + (*current_).first.length(); - return cname; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueConstIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueConstIterator::ValueConstIterator() = default; - -ValueConstIterator::ValueConstIterator( - const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueConstIterator::ValueConstIterator(ValueIterator const& other) - : ValueIteratorBase(other) {} - -ValueConstIterator& ValueConstIterator:: -operator=(const ValueIteratorBase& other) { - copy(other); - return *this; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class ValueIterator -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -ValueIterator::ValueIterator() = default; - -ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) - : ValueIteratorBase(current) {} - -ValueIterator::ValueIterator(const ValueConstIterator& other) - : ValueIteratorBase(other) { - throwRuntimeError("ConstIterator to Iterator should never be allowed."); -} - -ValueIterator::ValueIterator(const ValueIterator& other) = default; - -ValueIterator& ValueIterator::operator=(const SelfType& other) { - copy(other); - return *this; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_valueiterator.inl -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include -#include - -// Provide implementation equivalent of std::snprintf for older _MSC compilers -#if defined(_MSC_VER) && _MSC_VER < 1900 -#include -static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size, - const char* format, va_list ap) { - int count = -1; - if (size != 0) - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); - if (count == -1) - count = _vscprintf(format, ap); - return count; -} - -int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size, - const char* format, ...) { - va_list ap; - va_start(ap, format); - const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); - va_end(ap); - return count; -} -#endif - -// Disable warning C4702 : unreachable code -#if defined(_MSC_VER) -#pragma warning(disable : 4702) -#endif - -#define JSON_ASSERT_UNREACHABLE assert(false) - -namespace Json { -template -static std::unique_ptr cloneUnique(const std::unique_ptr& p) { - std::unique_ptr r; - if (p) { - r = std::unique_ptr(new T(*p)); - } - return r; -} - -// This is a walkaround to avoid the static initialization of Value::null. -// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of -// 8 (instead of 4) as a bit of future-proofing. -#if defined(__ARMEL__) -#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) -#else -#define ALIGNAS(byte_alignment) -#endif - -// static -Value const& Value::nullSingleton() { - static Value const nullStatic; - return nullStatic; -} - -#if JSON_USE_NULLREF -// for backwards compatibility, we'll leave these global references around, but -// DO NOT use them in JSONCPP library code any more! -// static -Value const& Value::null = Value::nullSingleton(); - -// static -Value const& Value::nullRef = Value::nullSingleton(); -#endif - -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -template -static inline bool InRange(double d, T min, U max) { - // The casts can lose precision, but we are looking only for - // an approximate range. Might fail on edge cases though. ~cdunn - return d >= static_cast(min) && d <= static_cast(max); -} -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) -static inline double integerToDouble(Json::UInt64 value) { - return static_cast(Int64(value / 2)) * 2.0 + - static_cast(Int64(value & 1)); -} - -template static inline double integerToDouble(T value) { - return static_cast(value); -} - -template -static inline bool InRange(double d, T min, U max) { - return d >= integerToDouble(min) && d <= integerToDouble(max); -} -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - -/** Duplicates the specified string value. - * @param value Pointer to the string to duplicate. Must be zero-terminated if - * length is "unknown". - * @param length Length of the value. if equals to unknown, then it will be - * computed using strlen(value). - * @return Pointer on the duplicate instance of string. - */ -static inline char* duplicateStringValue(const char* value, size_t length) { - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - if (length >= static_cast(Value::maxInt)) - length = Value::maxInt - 1; - - auto newString = static_cast(malloc(length + 1)); - if (newString == nullptr) { - throwRuntimeError("in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); - } - memcpy(newString, value, length); - newString[length] = 0; - return newString; -} - -/* Record the length as a prefix. - */ -static inline char* duplicateAndPrefixStringValue(const char* value, - unsigned int length) { - // Avoid an integer overflow in the call to malloc below by limiting length - // to a sane value. - JSON_ASSERT_MESSAGE(length <= static_cast(Value::maxInt) - - sizeof(unsigned) - 1U, - "in Json::Value::duplicateAndPrefixStringValue(): " - "length too big for prefixing"); - size_t actualLength = sizeof(length) + length + 1; - auto newString = static_cast(malloc(actualLength)); - if (newString == nullptr) { - throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); - } - *reinterpret_cast(newString) = length; - memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = - 0; // to avoid buffer over-run accidents by users later - return newString; -} -inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, - unsigned* length, char const** value) { - if (!isPrefixed) { - *length = static_cast(strlen(prefixed)); - *value = prefixed; - } else { - *length = *reinterpret_cast(prefixed); - *value = prefixed + sizeof(unsigned); - } -} -/** Free the string duplicated by - * duplicateStringValue()/duplicateAndPrefixStringValue(). - */ -#if JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { - unsigned length = 0; - char const* valueDecoded; - decodePrefixedString(true, value, &length, &valueDecoded); - size_t const size = sizeof(unsigned) + length + 1U; - memset(value, 0, size); - free(value); -} -static inline void releaseStringValue(char* value, unsigned length) { - // length==0 => we allocated the strings memory - size_t size = (length == 0) ? strlen(value) : length; - memset(value, 0, size); - free(value); -} -#else // !JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { free(value); } -static inline void releaseStringValue(char* value, unsigned) { free(value); } -#endif // JSONCPP_USING_SECURE_MEMORY - -} // namespace Json - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ValueInternals... -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -#if !defined(JSON_IS_AMALGAMATION) - -#include "json_valueiterator.inl" -#endif // if !defined(JSON_IS_AMALGAMATION) - -namespace Json { - -#if JSON_USE_EXCEPTION -Exception::Exception(String msg) : msg_(std::move(msg)) {} -Exception::~Exception() noexcept = default; -char const* Exception::what() const noexcept { return msg_.c_str(); } -RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} -LogicError::LogicError(String const& msg) : Exception(msg) {} -JSONCPP_NORETURN void throwRuntimeError(String const& msg) { - throw RuntimeError(msg); -} -JSONCPP_NORETURN void throwLogicError(String const& msg) { - throw LogicError(msg); -} -#else // !JSON_USE_EXCEPTION -JSONCPP_NORETURN void throwRuntimeError(String const& msg) { - std::cerr << msg << std::endl; - abort(); -} -JSONCPP_NORETURN void throwLogicError(String const& msg) { - std::cerr << msg << std::endl; - abort(); -} -#endif - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CZString -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -// Notes: policy_ indicates if the string was allocated when -// a string is stored. - -Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} - -Value::CZString::CZString(char const* str, unsigned length, - DuplicationPolicy allocate) - : cstr_(str) { - // allocate != duplicate - storage_.policy_ = allocate & 0x3; - storage_.length_ = length & 0x3FFFFFFF; -} - -Value::CZString::CZString(const CZString& other) { - cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_); - storage_.policy_ = - static_cast( - other.cstr_ - ? (static_cast(other.storage_.policy_) == - noDuplication - ? noDuplication - : duplicate) - : static_cast(other.storage_.policy_)) & - 3U; - storage_.length_ = other.storage_.length_; -} - -Value::CZString::CZString(CZString&& other) noexcept - : cstr_(other.cstr_), index_(other.index_) { - other.cstr_ = nullptr; -} - -Value::CZString::~CZString() { - if (cstr_ && storage_.policy_ == duplicate) { - releaseStringValue(const_cast(cstr_), - storage_.length_ + 1U); // +1 for null terminating - // character for sake of - // completeness but not actually - // necessary - } -} - -void Value::CZString::swap(CZString& other) { - std::swap(cstr_, other.cstr_); - std::swap(index_, other.index_); -} - -Value::CZString& Value::CZString::operator=(const CZString& other) { - cstr_ = other.cstr_; - index_ = other.index_; - return *this; -} - -Value::CZString& Value::CZString::operator=(CZString&& other) noexcept { - cstr_ = other.cstr_; - index_ = other.index_; - other.cstr_ = nullptr; - return *this; -} - -bool Value::CZString::operator<(const CZString& other) const { - if (!cstr_) - return index_ < other.index_; - // return strcmp(cstr_, other.cstr_) < 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - unsigned min_len = std::min(this_len, other_len); - JSON_ASSERT(this->cstr_ && other.cstr_); - int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; - return (this_len < other_len); -} - -bool Value::CZString::operator==(const CZString& other) const { - if (!cstr_) - return index_ == other.index_; - // return strcmp(cstr_, other.cstr_) == 0; - // Assume both are strings. - unsigned this_len = this->storage_.length_; - unsigned other_len = other.storage_.length_; - if (this_len != other_len) - return false; - JSON_ASSERT(this->cstr_ && other.cstr_); - int comp = memcmp(this->cstr_, other.cstr_, this_len); - return comp == 0; -} - -ArrayIndex Value::CZString::index() const { return index_; } - -// const char* Value::CZString::c_str() const { return cstr_; } -const char* Value::CZString::data() const { return cstr_; } -unsigned Value::CZString::length() const { return storage_.length_; } -bool Value::CZString::isStaticString() const { - return storage_.policy_ == noDuplication; -} - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::Value -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -/*! \internal Default constructor initialization must be equivalent to: - * memset( this, 0, sizeof(Value) ) - * This optimization is used in ValueInternalMap fast allocator. - */ -Value::Value(ValueType type) { - static char const emptyString[] = ""; - initBasic(type); - switch (type) { - case nullValue: - break; - case intValue: - case uintValue: - value_.int_ = 0; - break; - case realValue: - value_.real_ = 0.0; - break; - case stringValue: - // allocated_ == false, so this is safe. - value_.string_ = const_cast(static_cast(emptyString)); - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(); - break; - case booleanValue: - value_.bool_ = false; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -Value::Value(Int value) { - initBasic(intValue); - value_.int_ = value; -} - -Value::Value(UInt value) { - initBasic(uintValue); - value_.uint_ = value; -} -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) { - initBasic(intValue); - value_.int_ = value; -} -Value::Value(UInt64 value) { - initBasic(uintValue); - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) { - initBasic(realValue); - value_.real_ = value; -} - -Value::Value(const char* value) { - initBasic(stringValue, true); - JSON_ASSERT_MESSAGE(value != nullptr, - "Null Value Passed to Value Constructor"); - value_.string_ = duplicateAndPrefixStringValue( - value, static_cast(strlen(value))); -} - -Value::Value(const char* begin, const char* end) { - initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(begin, static_cast(end - begin)); -} - -Value::Value(const String& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue( - value.data(), static_cast(value.length())); -} - -Value::Value(const StaticString& value) { - initBasic(stringValue); - value_.string_ = const_cast(value.c_str()); -} - -Value::Value(bool value) { - initBasic(booleanValue); - value_.bool_ = value; -} - -Value::Value(const Value& other) { - dupPayload(other); - dupMeta(other); -} - -Value::Value(Value&& other) noexcept { - initBasic(nullValue); - swap(other); -} - -Value::~Value() { - releasePayload(); - value_.uint_ = 0; -} - -Value& Value::operator=(const Value& other) { - Value(other).swap(*this); - return *this; -} - -Value& Value::operator=(Value&& other) noexcept { - other.swap(*this); - return *this; -} - -void Value::swapPayload(Value& other) { - std::swap(bits_, other.bits_); - std::swap(value_, other.value_); -} - -void Value::copyPayload(const Value& other) { - releasePayload(); - dupPayload(other); -} - -void Value::swap(Value& other) { - swapPayload(other); - std::swap(comments_, other.comments_); - std::swap(start_, other.start_); - std::swap(limit_, other.limit_); -} - -void Value::copy(const Value& other) { - copyPayload(other); - dupMeta(other); -} - -ValueType Value::type() const { - return static_cast(bits_.value_type_); -} - -int Value::compare(const Value& other) const { - if (*this < other) - return -1; - if (*this > other) - return 1; - return 0; -} - -bool Value::operator<(const Value& other) const { - int typeDelta = type() - other.type(); - if (typeDelta) - return typeDelta < 0; - switch (type()) { - case nullValue: - return false; - case intValue: - return value_.int_ < other.value_.int_; - case uintValue: - return value_.uint_ < other.value_.uint_; - case realValue: - return value_.real_ < other.value_.real_; - case booleanValue: - return value_.bool_ < other.value_.bool_; - case stringValue: { - if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { - return other.value_.string_ != nullptr; - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, - &other_str); - unsigned min_len = std::min(this_len, other_len); - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) - return true; - if (comp > 0) - return false; - return (this_len < other_len); - } - case arrayValue: - case objectValue: { - auto thisSize = value_.map_->size(); - auto otherSize = other.value_.map_->size(); - if (thisSize != otherSize) - return thisSize < otherSize; - return (*value_.map_) < (*other.value_.map_); - } - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator<=(const Value& other) const { return !(other < *this); } - -bool Value::operator>=(const Value& other) const { return !(*this < other); } - -bool Value::operator>(const Value& other) const { return other < *this; } - -bool Value::operator==(const Value& other) const { - if (type() != other.type()) - return false; - switch (type()) { - case nullValue: - return true; - case intValue: - return value_.int_ == other.value_.int_; - case uintValue: - return value_.uint_ == other.value_.uint_; - case realValue: - return value_.real_ == other.value_.real_; - case booleanValue: - return value_.bool_ == other.value_.bool_; - case stringValue: { - if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { - return (value_.string_ == other.value_.string_); - } - unsigned this_len; - unsigned other_len; - char const* this_str; - char const* other_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, - &other_str); - if (this_len != other_len) - return false; - JSON_ASSERT(this_str && other_str); - int comp = memcmp(this_str, other_str, this_len); - return comp == 0; - } - case arrayValue: - case objectValue: - return value_.map_->size() == other.value_.map_->size() && - (*value_.map_) == (*other.value_.map_); - default: - JSON_ASSERT_UNREACHABLE; - } - return false; // unreachable -} - -bool Value::operator!=(const Value& other) const { return !(*this == other); } - -const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type() == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == nullptr) - return nullptr; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return this_str; -} - -#if JSONCPP_USING_SECURE_MEMORY -unsigned Value::getCStringLength() const { - JSON_ASSERT_MESSAGE(type() == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) - return 0; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return this_len; -} -#endif - -bool Value::getString(char const** begin, char const** end) const { - if (type() != stringValue) - return false; - if (value_.string_ == nullptr) - return false; - unsigned length; - decodePrefixedString(this->isAllocated(), this->value_.string_, &length, - begin); - *end = *begin + length; - return true; -} - -String Value::asString() const { - switch (type()) { - case nullValue: - return ""; - case stringValue: { - if (value_.string_ == nullptr) - return ""; - unsigned this_len; - char const* this_str; - decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, - &this_str); - return String(this_str, this_len); - } - case booleanValue: - return value_.bool_ ? "true" : "false"; - case intValue: - return valueToString(value_.int_); - case uintValue: - return valueToString(value_.uint_); - case realValue: - return valueToString(value_.real_); - default: - JSON_FAIL_MESSAGE("Type is not convertible to string"); - } -} - -Value::Int Value::asInt() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); - return Int(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); - return Int(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), - "double out of Int range"); - return Int(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int."); -} - -Value::UInt Value::asUInt() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); - return UInt(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); - return UInt(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), - "double out of UInt range"); - return UInt(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt."); -} - -#if defined(JSON_HAS_INT64) - -Value::Int64 Value::asInt64() const { - switch (type()) { - case intValue: - return Int64(value_.int_); - case uintValue: - JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); - return Int64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), - "double out of Int64 range"); - return Int64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to Int64."); -} - -Value::UInt64 Value::asUInt64() const { - switch (type()) { - case intValue: - JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); - return UInt64(value_.int_); - case uintValue: - return UInt64(value_.uint_); - case realValue: - JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), - "double out of UInt64 range"); - return UInt64(value_.real_); - case nullValue: - return 0; - case booleanValue: - return value_.bool_ ? 1 : 0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); -} -#endif // if defined(JSON_HAS_INT64) - -LargestInt Value::asLargestInt() const { -#if defined(JSON_NO_INT64) - return asInt(); -#else - return asInt64(); -#endif -} - -LargestUInt Value::asLargestUInt() const { -#if defined(JSON_NO_INT64) - return asUInt(); -#else - return asUInt64(); -#endif -} - -double Value::asDouble() const { - switch (type()) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return integerToDouble(value_.uint_); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return value_.real_; - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0 : 0.0; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to double."); -} - -float Value::asFloat() const { - switch (type()) { - case intValue: - return static_cast(value_.int_); - case uintValue: -#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - return static_cast(value_.uint_); -#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - // This can fail (silently?) if the value is bigger than MAX_FLOAT. - return static_cast(integerToDouble(value_.uint_)); -#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) - case realValue: - return static_cast(value_.real_); - case nullValue: - return 0.0; - case booleanValue: - return value_.bool_ ? 1.0F : 0.0F; - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to float."); -} - -bool Value::asBool() const { - switch (type()) { - case booleanValue: - return value_.bool_; - case nullValue: - return false; - case intValue: - return value_.int_ != 0; - case uintValue: - return value_.uint_ != 0; - case realValue: { - // According to JavaScript language zero or NaN is regarded as false - const auto value_classification = std::fpclassify(value_.real_); - return value_classification != FP_ZERO && value_classification != FP_NAN; - } - default: - break; - } - JSON_FAIL_MESSAGE("Value is not convertible to bool."); -} - -bool Value::isConvertibleTo(ValueType other) const { - switch (other) { - case nullValue: - return (isNumeric() && asDouble() == 0.0) || - (type() == booleanValue && !value_.bool_) || - (type() == stringValue && asString().empty()) || - (type() == arrayValue && value_.map_->empty()) || - (type() == objectValue && value_.map_->empty()) || - type() == nullValue; - case intValue: - return isInt() || - (type() == realValue && InRange(value_.real_, minInt, maxInt)) || - type() == booleanValue || type() == nullValue; - case uintValue: - return isUInt() || - (type() == realValue && InRange(value_.real_, 0, maxUInt)) || - type() == booleanValue || type() == nullValue; - case realValue: - return isNumeric() || type() == booleanValue || type() == nullValue; - case booleanValue: - return isNumeric() || type() == booleanValue || type() == nullValue; - case stringValue: - return isNumeric() || type() == booleanValue || type() == stringValue || - type() == nullValue; - case arrayValue: - return type() == arrayValue || type() == nullValue; - case objectValue: - return type() == objectValue || type() == nullValue; - } - JSON_ASSERT_UNREACHABLE; - return false; -} - -/// Number of values in array or object -ArrayIndex Value::size() const { - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - case stringValue: - return 0; - case arrayValue: // size of the array is highest index + 1 - if (!value_.map_->empty()) { - ObjectValues::const_iterator itLast = value_.map_->end(); - --itLast; - return (*itLast).first.index() + 1; - } - return 0; - case objectValue: - return ArrayIndex(value_.map_->size()); - } - JSON_ASSERT_UNREACHABLE; - return 0; // unreachable; -} - -bool Value::empty() const { - if (isNull() || isArray() || isObject()) - return size() == 0U; - return false; -} - -Value::operator bool() const { return !isNull(); } - -void Value::clear() { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || - type() == objectValue, - "in Json::Value::clear(): requires complex value"); - start_ = 0; - limit_ = 0; - switch (type()) { - case arrayValue: - case objectValue: - value_.map_->clear(); - break; - default: - break; - } -} - -void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::resize(): requires arrayValue"); - if (type() == nullValue) - *this = Value(arrayValue); - ArrayIndex oldSize = size(); - if (newSize == 0) - clear(); - else if (newSize > oldSize) - for (ArrayIndex i = oldSize; i < newSize; ++i) - (*this)[i]; - else { - for (ArrayIndex index = newSize; index < oldSize; ++index) { - value_.map_->erase(index); - } - JSON_ASSERT(size() == newSize); - } -} - -Value& Value::operator[](ArrayIndex index) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == arrayValue, - "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type() == nullValue) - *this = Value(arrayValue); - CZString key(index); - auto it = value_.map_->lower_bound(key); - if (it != value_.map_->end() && (*it).first == key) - return (*it).second; - - ObjectValues::value_type defaultValue(key, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - return (*it).second; -} - -Value& Value::operator[](int index) { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index): index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -const Value& Value::operator[](ArrayIndex index) const { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == arrayValue, - "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type() == nullValue) - return nullSingleton(); - CZString key(index); - ObjectValues::const_iterator it = value_.map_->find(key); - if (it == value_.map_->end()) - return nullSingleton(); - return (*it).second; -} - -const Value& Value::operator[](int index) const { - JSON_ASSERT_MESSAGE( - index >= 0, - "in Json::Value::operator[](int index) const: index cannot be negative"); - return (*this)[ArrayIndex(index)]; -} - -void Value::initBasic(ValueType type, bool allocated) { - setType(type); - setIsAllocated(allocated); - comments_ = Comments{}; - start_ = 0; - limit_ = 0; -} - -void Value::dupPayload(const Value& other) { - setType(other.type()); - setIsAllocated(false); - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.isAllocated()) { - unsigned len; - char const* str; - decodePrefixedString(other.isAllocated(), other.value_.string_, &len, - &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - setIsAllocated(true); - } else { - value_.string_ = other.value_.string_; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -void Value::releasePayload() { - switch (type()) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (isAllocated()) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } -} - -void Value::dupMeta(const Value& other) { - comments_ = other.comments_; - start_ = other.start_; - limit_ = other.limit_; -} - -// Access an object value by name, create a null member if it does not exist. -// @pre Type of '*this' is object or null. -// @param key is null-terminated. -Value& Value::resolveReference(const char* key) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(): requires objectValue"); - if (type() == nullValue) - *this = Value(objectValue); - CZString actualKey(key, static_cast(strlen(key)), - CZString::noDuplication); // NOTE! - auto it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -// @param key is not null-terminated. -Value& Value::resolveReference(char const* key, char const* end) { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::resolveReference(key, end): requires objectValue"); - if (type() == nullValue) - *this = Value(objectValue); - CZString actualKey(key, static_cast(end - key), - CZString::duplicateOnCopy); - auto it = value_.map_->lower_bound(actualKey); - if (it != value_.map_->end() && (*it).first == actualKey) - return (*it).second; - - ObjectValues::value_type defaultValue(actualKey, nullSingleton()); - it = value_.map_->insert(it, defaultValue); - Value& value = (*it).second; - return value; -} - -Value Value::get(ArrayIndex index, const Value& defaultValue) const { - const Value* value = &((*this)[index]); - return value == &nullSingleton() ? defaultValue : *value; -} - -bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } - -Value const* Value::find(char const* begin, char const* end) const { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::find(begin, end): requires " - "objectValue or nullValue"); - if (type() == nullValue) - return nullptr; - CZString actualKey(begin, static_cast(end - begin), - CZString::noDuplication); - ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return nullptr; - return &(*it).second; -} -Value* Value::demand(char const* begin, char const* end) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::demand(begin, end): requires " - "objectValue or nullValue"); - return &resolveReference(begin, end); -} -const Value& Value::operator[](const char* key) const { - Value const* found = find(key, key + strlen(key)); - if (!found) - return nullSingleton(); - return *found; -} -Value const& Value::operator[](const String& key) const { - Value const* found = find(key.data(), key.data() + key.length()); - if (!found) - return nullSingleton(); - return *found; -} - -Value& Value::operator[](const char* key) { - return resolveReference(key, key + strlen(key)); -} - -Value& Value::operator[](const String& key) { - return resolveReference(key.data(), key.data() + key.length()); -} - -Value& Value::operator[](const StaticString& key) { - return resolveReference(key.c_str()); -} - -Value& Value::append(const Value& value) { return append(Value(value)); } - -Value& Value::append(Value&& value) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::append: requires arrayValue"); - if (type() == nullValue) { - *this = Value(arrayValue); - } - return this->value_.map_->emplace(size(), std::move(value)).first->second; -} - -bool Value::insert(ArrayIndex index, const Value& newValue) { - return insert(index, Value(newValue)); -} - -bool Value::insert(ArrayIndex index, Value&& newValue) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, - "in Json::Value::insert: requires arrayValue"); - ArrayIndex length = size(); - if (index > length) { - return false; - } - for (ArrayIndex i = length; i > index; i--) { - (*this)[i] = std::move((*this)[i - 1]); - } - (*this)[index] = std::move(newValue); - return true; -} - -Value Value::get(char const* begin, char const* end, - Value const& defaultValue) const { - Value const* found = find(begin, end); - return !found ? defaultValue : *found; -} -Value Value::get(char const* key, Value const& defaultValue) const { - return get(key, key + strlen(key), defaultValue); -} -Value Value::get(String const& key, Value const& defaultValue) const { - return get(key.data(), key.data() + key.length(), defaultValue); -} - -bool Value::removeMember(const char* begin, const char* end, Value* removed) { - if (type() != objectValue) { - return false; - } - CZString actualKey(begin, static_cast(end - begin), - CZString::noDuplication); - auto it = value_.map_->find(actualKey); - if (it == value_.map_->end()) - return false; - if (removed) - *removed = std::move(it->second); - value_.map_->erase(it); - return true; -} -bool Value::removeMember(const char* key, Value* removed) { - return removeMember(key, key + strlen(key), removed); -} -bool Value::removeMember(String const& key, Value* removed) { - return removeMember(key.data(), key.data() + key.length(), removed); -} -void Value::removeMember(const char* key) { - JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, - "in Json::Value::removeMember(): requires objectValue"); - if (type() == nullValue) - return; - - CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); - value_.map_->erase(actualKey); -} -void Value::removeMember(const String& key) { removeMember(key.c_str()); } - -bool Value::removeIndex(ArrayIndex index, Value* removed) { - if (type() != arrayValue) { - return false; - } - CZString key(index); - auto it = value_.map_->find(key); - if (it == value_.map_->end()) { - return false; - } - if (removed) - *removed = it->second; - ArrayIndex oldSize = size(); - // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i) { - CZString keey(i); - (*value_.map_)[keey] = (*this)[i + 1]; - } - // erase the last one ("leftover") - CZString keyLast(oldSize - 1); - auto itLast = value_.map_->find(keyLast); - value_.map_->erase(itLast); - return true; -} - -bool Value::isMember(char const* begin, char const* end) const { - Value const* value = find(begin, end); - return nullptr != value; -} -bool Value::isMember(char const* key) const { - return isMember(key, key + strlen(key)); -} -bool Value::isMember(String const& key) const { - return isMember(key.data(), key.data() + key.length()); -} - -Value::Members Value::getMemberNames() const { - JSON_ASSERT_MESSAGE( - type() == nullValue || type() == objectValue, - "in Json::Value::getMemberNames(), value must be objectValue"); - if (type() == nullValue) - return Value::Members(); - Members members; - members.reserve(value_.map_->size()); - ObjectValues::const_iterator it = value_.map_->begin(); - ObjectValues::const_iterator itEnd = value_.map_->end(); - for (; it != itEnd; ++it) { - members.push_back(String((*it).first.data(), (*it).first.length())); - } - return members; -} - -static bool IsIntegral(double d) { - double integral_part; - return modf(d, &integral_part) == 0.0; -} - -bool Value::isNull() const { return type() == nullValue; } - -bool Value::isBool() const { return type() == booleanValue; } - -bool Value::isInt() const { - switch (type()) { - case intValue: -#if defined(JSON_HAS_INT64) - return value_.int_ >= minInt && value_.int_ <= maxInt; -#else - return true; -#endif - case uintValue: - return value_.uint_ <= UInt(maxInt); - case realValue: - return value_.real_ >= minInt && value_.real_ <= maxInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isUInt() const { - switch (type()) { - case intValue: -#if defined(JSON_HAS_INT64) - return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); -#else - return value_.int_ >= 0; -#endif - case uintValue: -#if defined(JSON_HAS_INT64) - return value_.uint_ <= maxUInt; -#else - return true; -#endif - case realValue: - return value_.real_ >= 0 && value_.real_ <= maxUInt && - IsIntegral(value_.real_); - default: - break; - } - return false; -} - -bool Value::isInt64() const { -#if defined(JSON_HAS_INT64) - switch (type()) { - case intValue: - return true; - case uintValue: - return value_.uint_ <= UInt64(maxInt64); - case realValue: - // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a - // double, so double(maxInt64) will be rounded up to 2^63. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < double(maxInt64) && IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isUInt64() const { -#if defined(JSON_HAS_INT64) - switch (type()) { - case intValue: - return value_.int_ >= 0; - case uintValue: - return true; - case realValue: - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && - IsIntegral(value_.real_); - default: - break; - } -#endif // JSON_HAS_INT64 - return false; -} - -bool Value::isIntegral() const { - switch (type()) { - case intValue: - case uintValue: - return true; - case realValue: -#if defined(JSON_HAS_INT64) - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && - value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); -#else - return value_.real_ >= minInt && value_.real_ <= maxUInt && - IsIntegral(value_.real_); -#endif // JSON_HAS_INT64 - default: - break; - } - return false; -} - -bool Value::isDouble() const { - return type() == intValue || type() == uintValue || type() == realValue; -} - -bool Value::isNumeric() const { return isDouble(); } - -bool Value::isString() const { return type() == stringValue; } - -bool Value::isArray() const { return type() == arrayValue; } - -bool Value::isObject() const { return type() == objectValue; } - -Value::Comments::Comments(const Comments& that) - : ptr_{cloneUnique(that.ptr_)} {} - -Value::Comments::Comments(Comments&& that) noexcept - : ptr_{std::move(that.ptr_)} {} - -Value::Comments& Value::Comments::operator=(const Comments& that) { - ptr_ = cloneUnique(that.ptr_); - return *this; -} - -Value::Comments& Value::Comments::operator=(Comments&& that) noexcept { - ptr_ = std::move(that.ptr_); - return *this; -} - -bool Value::Comments::has(CommentPlacement slot) const { - return ptr_ && !(*ptr_)[slot].empty(); -} - -String Value::Comments::get(CommentPlacement slot) const { - if (!ptr_) - return {}; - return (*ptr_)[slot]; -} - -void Value::Comments::set(CommentPlacement slot, String comment) { - if (slot >= CommentPlacement::numberOfCommentPlacement) - return; - if (!ptr_) - ptr_ = std::unique_ptr(new Array()); - (*ptr_)[slot] = std::move(comment); -} - -void Value::setComment(String comment, CommentPlacement placement) { - if (!comment.empty() && (comment.back() == '\n')) { - // Always discard trailing newline, to aid indentation. - comment.pop_back(); - } - JSON_ASSERT(!comment.empty()); - JSON_ASSERT_MESSAGE( - comment[0] == '\0' || comment[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - comments_.set(placement, std::move(comment)); -} - -bool Value::hasComment(CommentPlacement placement) const { - return comments_.has(placement); -} - -String Value::getComment(CommentPlacement placement) const { - return comments_.get(placement); -} - -void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } - -void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; } - -ptrdiff_t Value::getOffsetStart() const { return start_; } - -ptrdiff_t Value::getOffsetLimit() const { return limit_; } - -String Value::toStyledString() const { - StreamWriterBuilder builder; - - String out = this->hasComment(commentBefore) ? "\n" : ""; - out += Json::writeString(builder, *this); - out += '\n'; - - return out; -} - -Value::const_iterator Value::begin() const { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->begin()); - break; - default: - break; - } - return {}; -} - -Value::const_iterator Value::end() const { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return const_iterator(value_.map_->end()); - break; - default: - break; - } - return {}; -} - -Value::iterator Value::begin() { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->begin()); - break; - default: - break; - } - return iterator(); -} - -Value::iterator Value::end() { - switch (type()) { - case arrayValue: - case objectValue: - if (value_.map_) - return iterator(value_.map_->end()); - break; - default: - break; - } - return iterator(); -} - -// class PathArgument -// ////////////////////////////////////////////////////////////////// - -PathArgument::PathArgument() = default; - -PathArgument::PathArgument(ArrayIndex index) - : index_(index), kind_(kindIndex) {} - -PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {} - -PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {} - -// class Path -// ////////////////////////////////////////////////////////////////// - -Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2, - const PathArgument& a3, const PathArgument& a4, - const PathArgument& a5) { - InArgs in; - in.reserve(5); - in.push_back(&a1); - in.push_back(&a2); - in.push_back(&a3); - in.push_back(&a4); - in.push_back(&a5); - makePath(path, in); -} - -void Path::makePath(const String& path, const InArgs& in) { - const char* current = path.c_str(); - const char* end = current + path.length(); - auto itInArg = in.begin(); - while (current != end) { - if (*current == '[') { - ++current; - if (*current == '%') - addPathInArg(path, in, itInArg, PathArgument::kindIndex); - else { - ArrayIndex index = 0; - for (; current != end && *current >= '0' && *current <= '9'; ++current) - index = index * 10 + ArrayIndex(*current - '0'); - args_.push_back(index); - } - if (current == end || *++current != ']') - invalidPath(path, int(current - path.c_str())); - } else if (*current == '%') { - addPathInArg(path, in, itInArg, PathArgument::kindKey); - ++current; - } else if (*current == '.' || *current == ']') { - ++current; - } else { - const char* beginName = current; - while (current != end && !strchr("[.", *current)) - ++current; - args_.push_back(String(beginName, current)); - } - } -} - -void Path::addPathInArg(const String& /*path*/, const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind) { - if (itInArg == in.end()) { - // Error: missing argument %d - } else if ((*itInArg)->kind_ != kind) { - // Error: bad argument type - } else { - args_.push_back(**itInArg++); - } -} - -void Path::invalidPath(const String& /*path*/, int /*location*/) { - // Error: invalid path. -} - -const Value& Path::resolve(const Value& root) const { - const Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... ) - return Value::nullSingleton(); - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: unable to resolve path (object value expected at position...) - return Value::nullSingleton(); - } - node = &((*node)[arg.key_]); - if (node == &Value::nullSingleton()) { - // Error: unable to resolve path (object has no member named '' at - // position...) - return Value::nullSingleton(); - } - } - } - return *node; -} - -Value Path::resolve(const Value& root, const Value& defaultValue) const { - const Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray() || !node->isValidIndex(arg.index_)) - return defaultValue; - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) - return defaultValue; - node = &((*node)[arg.key_]); - if (node == &Value::nullSingleton()) - return defaultValue; - } - } - return *node; -} - -Value& Path::make(Value& root) const { - Value* node = &root; - for (const auto& arg : args_) { - if (arg.kind_ == PathArgument::kindIndex) { - if (!node->isArray()) { - // Error: node is not an array at position ... - } - node = &((*node)[arg.index_]); - } else if (arg.kind_ == PathArgument::kindKey) { - if (!node->isObject()) { - // Error: node is not an object at position... - } - node = &((*node)[arg.key_]); - } - } - return *node; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_value.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - - -// ////////////////////////////////////////////////////////////////////// -// Beginning of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - -// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors -// Distributed under MIT license, or public domain if desired and -// recognized in your jurisdiction. -// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE - -#if !defined(JSON_IS_AMALGAMATION) -#include "json_tool.h" -#include -#endif // if !defined(JSON_IS_AMALGAMATION) -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if __cplusplus >= 201103L -#include -#include - -#if !defined(isnan) -#define isnan std::isnan -#endif - -#if !defined(isfinite) -#define isfinite std::isfinite -#endif - -#else -#include -#include - -#if defined(_MSC_VER) -#if !defined(isnan) -#include -#define isnan _isnan -#endif - -#if !defined(isfinite) -#include -#define isfinite _finite -#endif - -#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) -#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 -#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES - -#endif //_MSC_VER - -#if defined(__sun) && defined(__SVR4) // Solaris -#if !defined(isfinite) -#include -#define isfinite finite -#endif -#endif - -#if defined(__hpux) -#if !defined(isfinite) -#if defined(__ia64) && !defined(finite) -#define isfinite(x) \ - ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) -#endif -#endif -#endif - -#if !defined(isnan) -// IEEE standard states that NaN values will not compare to themselves -#define isnan(x) ((x) != (x)) -#endif - -#if !defined(__APPLE__) -#if !defined(isfinite) -#define isfinite finite -#endif -#endif -#endif - -#if defined(_MSC_VER) -// Disable warning about strdup being deprecated. -#pragma warning(disable : 4996) -#endif - -namespace Json { - -#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -using StreamWriterPtr = std::unique_ptr; -#else -using StreamWriterPtr = std::auto_ptr; -#endif - -String valueToString(LargestInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - if (value == Value::minLargestInt) { - uintToString(LargestUInt(Value::maxLargestInt) + 1, current); - *--current = '-'; - } else if (value < 0) { - uintToString(LargestUInt(-value), current); - *--current = '-'; - } else { - uintToString(LargestUInt(value), current); - } - assert(current >= buffer); - return current; -} - -String valueToString(LargestUInt value) { - UIntToStringBuffer buffer; - char* current = buffer + sizeof(buffer); - uintToString(value, current); - assert(current >= buffer); - return current; -} - -#if defined(JSON_HAS_INT64) - -String valueToString(Int value) { return valueToString(LargestInt(value)); } - -String valueToString(UInt value) { return valueToString(LargestUInt(value)); } - -#endif // # if defined(JSON_HAS_INT64) - -namespace { -String valueToString(double value, bool useSpecialFloats, - unsigned int precision, PrecisionType precisionType) { - // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distinguish the - // concepts of reals and integers. - if (!isfinite(value)) { - static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, - {"null", "-1e+9999", "1e+9999"}}; - return reps[useSpecialFloats ? 0 : 1] - [isnan(value) ? 0 : (value < 0) ? 1 : 2]; - } - - String buffer(size_t(36), '\0'); - while (true) { - int len = jsoncpp_snprintf( - &*buffer.begin(), buffer.size(), - (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", - precision, value); - assert(len >= 0); - auto wouldPrint = static_cast(len); - if (wouldPrint >= buffer.size()) { - buffer.resize(wouldPrint + 1); - continue; - } - buffer.resize(wouldPrint); - break; - } - - buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); - - // try to ensure we preserve the fact that this was given to us as a double on - // input - if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { - buffer += ".0"; - } - - // strip the zero padding from the right - if (precisionType == PrecisionType::decimalPlaces) { - buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision), - buffer.end()); - } - - return buffer; -} -} // namespace - -String valueToString(double value, unsigned int precision, - PrecisionType precisionType) { - return valueToString(value, false, precision, precisionType); -} - -String valueToString(bool value) { return value ? "true" : "false"; } - -static bool doesAnyCharRequireEscaping(char const* s, size_t n) { - assert(s || !n); - - return std::any_of(s, s + n, [](unsigned char c) { - return c == '\\' || c == '"' || c < 0x20 || c > 0x7F; - }); -} - -static unsigned int utf8ToCodepoint(const char*& s, const char* e) { - const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; - - unsigned int firstByte = static_cast(*s); - - if (firstByte < 0x80) - return firstByte; - - if (firstByte < 0xE0) { - if (e - s < 2) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = - ((firstByte & 0x1F) << 6) | (static_cast(s[1]) & 0x3F); - s += 1; - // oversized encoded characters are invalid - return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; - } - - if (firstByte < 0xF0) { - if (e - s < 3) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = ((firstByte & 0x0F) << 12) | - ((static_cast(s[1]) & 0x3F) << 6) | - (static_cast(s[2]) & 0x3F); - s += 2; - // surrogates aren't valid codepoints itself - // shouldn't be UTF-8 encoded - if (calculated >= 0xD800 && calculated <= 0xDFFF) - return REPLACEMENT_CHARACTER; - // oversized encoded characters are invalid - return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; - } - - if (firstByte < 0xF8) { - if (e - s < 4) - return REPLACEMENT_CHARACTER; - - unsigned int calculated = ((firstByte & 0x07) << 18) | - ((static_cast(s[1]) & 0x3F) << 12) | - ((static_cast(s[2]) & 0x3F) << 6) | - (static_cast(s[3]) & 0x3F); - s += 3; - // oversized encoded characters are invalid - return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; - } - - return REPLACEMENT_CHARACTER; -} - -static const char hex2[] = "000102030405060708090a0b0c0d0e0f" - "101112131415161718191a1b1c1d1e1f" - "202122232425262728292a2b2c2d2e2f" - "303132333435363738393a3b3c3d3e3f" - "404142434445464748494a4b4c4d4e4f" - "505152535455565758595a5b5c5d5e5f" - "606162636465666768696a6b6c6d6e6f" - "707172737475767778797a7b7c7d7e7f" - "808182838485868788898a8b8c8d8e8f" - "909192939495969798999a9b9c9d9e9f" - "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" - "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" - "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" - "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" - "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" - "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; - -static String toHex16Bit(unsigned int x) { - const unsigned int hi = (x >> 8) & 0xff; - const unsigned int lo = x & 0xff; - String result(4, ' '); - result[0] = hex2[2 * hi]; - result[1] = hex2[2 * hi + 1]; - result[2] = hex2[2 * lo]; - result[3] = hex2[2 * lo + 1]; - return result; -} - -static void appendRaw(String& result, unsigned ch) { - result += static_cast(ch); -} - -static void appendHex(String& result, unsigned ch) { - result.append("\\u").append(toHex16Bit(ch)); -} - -static String valueToQuotedStringN(const char* value, size_t length, - bool emitUTF8 = false) { - if (value == nullptr) - return ""; - - if (!doesAnyCharRequireEscaping(value, length)) - return String("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to String is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL - String result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - char const* end = value + length; - for (const char* c = value; c != end; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something.) - // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); - if (codepoint < 0x20) { - appendHex(result, codepoint); - } else { - appendRaw(result, codepoint); - } - } else { - unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c` - if (codepoint < 0x20) { - appendHex(result, codepoint); - } else if (codepoint < 0x80) { - appendRaw(result, codepoint); - } else if (codepoint < 0x10000) { - // Basic Multilingual Plane - appendHex(result, codepoint); - } else { - // Extended Unicode. Encode 20 bits as a surrogate pair. - codepoint -= 0x10000; - appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff)); - appendHex(result, 0xdc00 + (codepoint & 0x3ff)); - } - } - } break; - } - } - result += "\""; - return result; -} - -String valueToQuotedString(const char* value) { - return valueToQuotedStringN(value, strlen(value)); -} - -// Class Writer -// ////////////////////////////////////////////////////////////////// -Writer::~Writer() = default; - -// Class FastWriter -// ////////////////////////////////////////////////////////////////// - -FastWriter::FastWriter() - - = default; - -void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } - -void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } - -void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } - -String FastWriter::write(const Value& root) { - document_.clear(); - writeValue(root); - if (!omitEndingLineFeed_) - document_ += '\n'; - return document_; -} - -void FastWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - if (!dropNullPlaceholders_) - document_ += "null"; - break; - case intValue: - document_ += valueToString(value.asLargestInt()); - break; - case uintValue: - document_ += valueToString(value.asLargestUInt()); - break; - case realValue: - document_ += valueToString(value.asDouble()); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - document_ += valueToQuotedStringN(str, static_cast(end - str)); - break; - } - case booleanValue: - document_ += valueToString(value.asBool()); - break; - case arrayValue: { - document_ += '['; - ArrayIndex size = value.size(); - for (ArrayIndex index = 0; index < size; ++index) { - if (index > 0) - document_ += ','; - writeValue(value[index]); - } - document_ += ']'; - } break; - case objectValue: { - Value::Members members(value.getMemberNames()); - document_ += '{'; - for (auto it = members.begin(); it != members.end(); ++it) { - const String& name = *it; - if (it != members.begin()) - document_ += ','; - document_ += valueToQuotedStringN(name.data(), name.length()); - document_ += yamlCompatibilityEnabled_ ? ": " : ":"; - writeValue(value[name]); - } - document_ += '}'; - } break; - } -} - -// Class StyledWriter -// ////////////////////////////////////////////////////////////////// - -StyledWriter::StyledWriter() = default; - -String StyledWriter::write(const Value& root) { - document_.clear(); - addChildValues_ = false; - indentString_.clear(); - writeCommentBeforeValue(root); - writeValue(root); - writeCommentAfterValueOnSameLine(root); - document_ += '\n'; - return document_; -} - -void StyledWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue(valueToQuotedStringN(str, static_cast(end - str))); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - const String& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - document_ += " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledWriter::writeArrayValue(const Value& value) { - size_t size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultilineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - ArrayIndex index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - writeIndent(); - writeValue(childValue); - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - document_ += ','; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - document_ += "[ "; - for (size_t index = 0; index < size; ++index) { - if (index > 0) - document_ += ", "; - document_ += childValues_[index]; - } - document_ += " ]"; - } - } -} - -bool StyledWriter::isMultilineArray(const Value& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledWriter::pushValue(const String& value) { - if (addChildValues_) - childValues_.push_back(value); - else - document_ += value; -} - -void StyledWriter::writeIndent() { - if (!document_.empty()) { - char last = document_[document_.length() - 1]; - if (last == ' ') // already indented - return; - if (last != '\n') // Comments may add new-line - document_ += '\n'; - } - document_ += indentString_; -} - -void StyledWriter::writeWithIndent(const String& value) { - writeIndent(); - document_ += value; -} - -void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); } - -void StyledWriter::unindent() { - assert(indentString_.size() >= indentSize_); - indentString_.resize(indentString_.size() - indentSize_); -} - -void StyledWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - document_ += '\n'; - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - document_ += *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - writeIndent(); - ++iter; - } - - // Comments are stripped of trailing newlines, so add one here - document_ += '\n'; -} - -void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - document_ += " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - document_ += '\n'; - document_ += root.getComment(commentAfter); - document_ += '\n'; - } -} - -bool StyledWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -// Class StyledStreamWriter -// ////////////////////////////////////////////////////////////////// - -StyledStreamWriter::StyledStreamWriter(String indentation) - : document_(nullptr), indentation_(std::move(indentation)), - addChildValues_(), indented_(false) {} - -void StyledStreamWriter::write(OStream& out, const Value& root) { - document_ = &out; - addChildValues_ = false; - indentString_.clear(); - indented_ = true; - writeCommentBeforeValue(root); - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *document_ << "\n"; - document_ = nullptr; // Forget the stream, for safety. -} - -void StyledStreamWriter::writeValue(const Value& value) { - switch (value.type()) { - case nullValue: - pushValue("null"); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble())); - break; - case stringValue: { - // Is NULL possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue(valueToQuotedStringN(str, static_cast(end - str))); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - const String& name = *it; - const Value& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedString(name.c_str())); - *document_ << " : "; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void StyledStreamWriter::writeArrayValue(const Value& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isArrayMultiLine = isMultilineArray(value); - if (isArrayMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - const Value& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *document_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *document_ << "[ "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *document_ << ", "; - *document_ << childValues_[index]; - } - *document_ << " ]"; - } - } -} - -bool StyledStreamWriter::isMultilineArray(const Value& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - const Value& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void StyledStreamWriter::pushValue(const String& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *document_ << value; -} - -void StyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - *document_ << '\n' << indentString_; -} - -void StyledStreamWriter::writeWithIndent(const String& value) { - if (!indented_) - writeIndent(); - *document_ << value; - indented_ = false; -} - -void StyledStreamWriter::indent() { indentString_ += indentation_; } - -void StyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *document_ << *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would include newline - *document_ << indentString_; - ++iter; - } - indented_ = false; -} - -void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { - if (root.hasComment(commentAfterOnSameLine)) - *document_ << ' ' << root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *document_ << root.getComment(commentAfter); - } - indented_ = false; -} - -bool StyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -////////////////////////// -// BuiltStyledStreamWriter - -/// Scoped enums are not available until C++11. -struct CommentStyle { - /// Decide whether to write comments. - enum Enum { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. - }; -}; - -struct BuiltStyledStreamWriter : public StreamWriter { - BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs, - String colonSymbol, String nullSymbol, - String endingLineFeedSymbol, bool useSpecialFloats, - bool emitUTF8, unsigned int precision, - PrecisionType precisionType); - int write(Value const& root, OStream* sout) override; - -private: - void writeValue(Value const& value); - void writeArrayValue(Value const& value); - bool isMultilineArray(Value const& value); - void pushValue(String const& value); - void writeIndent(); - void writeWithIndent(String const& value); - void indent(); - void unindent(); - void writeCommentBeforeValue(Value const& root); - void writeCommentAfterValueOnSameLine(Value const& root); - static bool hasCommentForValue(const Value& value); - - using ChildValues = std::vector; - - ChildValues childValues_; - String indentString_; - unsigned int rightMargin_; - String indentation_; - CommentStyle::Enum cs_; - String colonSymbol_; - String nullSymbol_; - String endingLineFeedSymbol_; - bool addChildValues_ : 1; - bool indented_ : 1; - bool useSpecialFloats_ : 1; - bool emitUTF8_ : 1; - unsigned int precision_; - PrecisionType precisionType_; -}; -BuiltStyledStreamWriter::BuiltStyledStreamWriter( - String indentation, CommentStyle::Enum cs, String colonSymbol, - String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats, - bool emitUTF8, unsigned int precision, PrecisionType precisionType) - : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs), - colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)), - endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), - addChildValues_(false), indented_(false), - useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8), - precision_(precision), precisionType_(precisionType) {} -int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) { - sout_ = sout; - addChildValues_ = false; - indented_ = true; - indentString_.clear(); - writeCommentBeforeValue(root); - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(root); - writeCommentAfterValueOnSameLine(root); - *sout_ << endingLineFeedSymbol_; - sout_ = nullptr; - return 0; -} -void BuiltStyledStreamWriter::writeValue(Value const& value) { - switch (value.type()) { - case nullValue: - pushValue(nullSymbol_); - break; - case intValue: - pushValue(valueToString(value.asLargestInt())); - break; - case uintValue: - pushValue(valueToString(value.asLargestUInt())); - break; - case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, - precisionType_)); - break; - case stringValue: { - // Is NULL is possible for value.string_? No. - char const* str; - char const* end; - bool ok = value.getString(&str, &end); - if (ok) - pushValue( - valueToQuotedStringN(str, static_cast(end - str), emitUTF8_)); - else - pushValue(""); - break; - } - case booleanValue: - pushValue(valueToString(value.asBool())); - break; - case arrayValue: - writeArrayValue(value); - break; - case objectValue: { - Value::Members members(value.getMemberNames()); - if (members.empty()) - pushValue("{}"); - else { - writeWithIndent("{"); - indent(); - auto it = members.begin(); - for (;;) { - String const& name = *it; - Value const& childValue = value[name]; - writeCommentBeforeValue(childValue); - writeWithIndent( - valueToQuotedStringN(name.data(), name.length(), emitUTF8_)); - *sout_ << colonSymbol_; - writeValue(childValue); - if (++it == members.end()) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("}"); - } - } break; - } -} - -void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { - unsigned size = value.size(); - if (size == 0) - pushValue("[]"); - else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); - if (isMultiLine) { - writeWithIndent("["); - indent(); - bool hasChildValue = !childValues_.empty(); - unsigned index = 0; - for (;;) { - Value const& childValue = value[index]; - writeCommentBeforeValue(childValue); - if (hasChildValue) - writeWithIndent(childValues_[index]); - else { - if (!indented_) - writeIndent(); - indented_ = true; - writeValue(childValue); - indented_ = false; - } - if (++index == size) { - writeCommentAfterValueOnSameLine(childValue); - break; - } - *sout_ << ","; - writeCommentAfterValueOnSameLine(childValue); - } - unindent(); - writeWithIndent("]"); - } else // output on a single line - { - assert(childValues_.size() == size); - *sout_ << "["; - if (!indentation_.empty()) - *sout_ << " "; - for (unsigned index = 0; index < size; ++index) { - if (index > 0) - *sout_ << ((!indentation_.empty()) ? ", " : ","); - *sout_ << childValues_[index]; - } - if (!indentation_.empty()) - *sout_ << " "; - *sout_ << "]"; - } - } -} - -bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { - ArrayIndex const size = value.size(); - bool isMultiLine = size * 3 >= rightMargin_; - childValues_.clear(); - for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { - Value const& childValue = value[index]; - isMultiLine = ((childValue.isArray() || childValue.isObject()) && - !childValue.empty()); - } - if (!isMultiLine) // check if line length > max line length - { - childValues_.reserve(size); - addChildValues_ = true; - ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' - for (ArrayIndex index = 0; index < size; ++index) { - if (hasCommentForValue(value[index])) { - isMultiLine = true; - } - writeValue(value[index]); - lineLength += static_cast(childValues_[index].length()); - } - addChildValues_ = false; - isMultiLine = isMultiLine || lineLength >= rightMargin_; - } - return isMultiLine; -} - -void BuiltStyledStreamWriter::pushValue(String const& value) { - if (addChildValues_) - childValues_.push_back(value); - else - *sout_ << value; -} - -void BuiltStyledStreamWriter::writeIndent() { - // blep intended this to look at the so-far-written string - // to determine whether we are already indented, but - // with a stream we cannot do that. So we rely on some saved state. - // The caller checks indented_. - - if (!indentation_.empty()) { - // In this case, drop newlines too. - *sout_ << '\n' << indentString_; - } -} - -void BuiltStyledStreamWriter::writeWithIndent(String const& value) { - if (!indented_) - writeIndent(); - *sout_ << value; - indented_ = false; -} - -void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } - -void BuiltStyledStreamWriter::unindent() { - assert(indentString_.size() >= indentation_.size()); - indentString_.resize(indentString_.size() - indentation_.size()); -} - -void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { - if (cs_ == CommentStyle::None) - return; - if (!root.hasComment(commentBefore)) - return; - - if (!indented_) - writeIndent(); - const String& comment = root.getComment(commentBefore); - String::const_iterator iter = comment.begin(); - while (iter != comment.end()) { - *sout_ << *iter; - if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) - // writeIndent(); // would write extra newline - *sout_ << indentString_; - ++iter; - } - indented_ = false; -} - -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( - Value const& root) { - if (cs_ == CommentStyle::None) - return; - if (root.hasComment(commentAfterOnSameLine)) - *sout_ << " " + root.getComment(commentAfterOnSameLine); - - if (root.hasComment(commentAfter)) { - writeIndent(); - *sout_ << root.getComment(commentAfter); - } -} - -// static -bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { - return value.hasComment(commentBefore) || - value.hasComment(commentAfterOnSameLine) || - value.hasComment(commentAfter); -} - -/////////////// -// StreamWriter - -StreamWriter::StreamWriter() : sout_(nullptr) {} -StreamWriter::~StreamWriter() = default; -StreamWriter::Factory::~Factory() = default; -StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } -StreamWriterBuilder::~StreamWriterBuilder() = default; -StreamWriter* StreamWriterBuilder::newStreamWriter() const { - const String indentation = settings_["indentation"].asString(); - const String cs_str = settings_["commentStyle"].asString(); - const String pt_str = settings_["precisionType"].asString(); - const bool eyc = settings_["enableYAMLCompatibility"].asBool(); - const bool dnp = settings_["dropNullPlaceholders"].asBool(); - const bool usf = settings_["useSpecialFloats"].asBool(); - const bool emitUTF8 = settings_["emitUTF8"].asBool(); - unsigned int pre = settings_["precision"].asUInt(); - CommentStyle::Enum cs = CommentStyle::All; - if (cs_str == "All") { - cs = CommentStyle::All; - } else if (cs_str == "None") { - cs = CommentStyle::None; - } else { - throwRuntimeError("commentStyle must be 'All' or 'None'"); - } - PrecisionType precisionType(significantDigits); - if (pt_str == "significant") { - precisionType = PrecisionType::significantDigits; - } else if (pt_str == "decimal") { - precisionType = PrecisionType::decimalPlaces; - } else { - throwRuntimeError("precisionType must be 'significant' or 'decimal'"); - } - String colonSymbol = " : "; - if (eyc) { - colonSymbol = ": "; - } else if (indentation.empty()) { - colonSymbol = ":"; - } - String nullSymbol = "null"; - if (dnp) { - nullSymbol.clear(); - } - if (pre > 17) - pre = 17; - String endingLineFeedSymbol; - return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, - endingLineFeedSymbol, usf, emitUTF8, pre, - precisionType); -} - -bool StreamWriterBuilder::validate(Json::Value* invalid) const { - static const auto& valid_keys = *new std::set{ - "indentation", - "commentStyle", - "enableYAMLCompatibility", - "dropNullPlaceholders", - "useSpecialFloats", - "emitUTF8", - "precision", - "precisionType", - }; - for (auto si = settings_.begin(); si != settings_.end(); ++si) { - auto key = si.name(); - if (valid_keys.count(key)) - continue; - if (invalid) - (*invalid)[key] = *si; - else - return false; - } - return invalid ? invalid->empty() : true; -} - -Value& StreamWriterBuilder::operator[](const String& key) { - return settings_[key]; -} -// static -void StreamWriterBuilder::setDefaults(Json::Value* settings) { - //! [StreamWriterBuilderDefaults] - (*settings)["commentStyle"] = "All"; - (*settings)["indentation"] = "\t"; - (*settings)["enableYAMLCompatibility"] = false; - (*settings)["dropNullPlaceholders"] = false; - (*settings)["useSpecialFloats"] = false; - (*settings)["emitUTF8"] = false; - (*settings)["precision"] = 17; - (*settings)["precisionType"] = "significant"; - //! [StreamWriterBuilderDefaults] -} - -String writeString(StreamWriter::Factory const& factory, Value const& root) { - OStringStream sout; - StreamWriterPtr const writer(factory.newStreamWriter()); - writer->write(root, &sout); - return sout.str(); -} - -OStream& operator<<(OStream& sout, Value const& root) { - StreamWriterBuilder builder; - StreamWriterPtr const writer(builder.newStreamWriter()); - writer->write(root, &sout); - return sout; -} - -} // namespace Json - -// ////////////////////////////////////////////////////////////////////// -// End of content of file: src/lib_json/json_writer.cpp -// ////////////////////////////////////////////////////////////////////// - - - - - diff --git a/src/communication/pub_gps/src/pub_gps_node.cpp b/src/communication/pub_gps/src/pub_gps_node.cpp deleted file mode 100644 index 6bbe8e9..0000000 --- a/src/communication/pub_gps/src/pub_gps_node.cpp +++ /dev/null @@ -1,305 +0,0 @@ -#include "MQTTClient.h" -#include "rclcpp/rclcpp.hpp" -#include "sweeper_interfaces/msg/rtk.hpp" -#include "json.h" -#include "pub_gps_node.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct MqttConf -{ - std::string address; // 形如 tcp://ip:port - std::string client_id; // 客户端 ID - std::string user; - std::string password; - std::string pub_gps_topic; - int qos = 1; - long timeout_ms = 10000L; - int reconnect_interval = 5000; // 重连间隔(ms) -} g_conf; - -GPS gps_mes; -// 增加连接状态标志,确保线程安全 -static bool is_connected = false; -static pthread_mutex_t connect_mutex = PTHREAD_MUTEX_INITIALIZER; - -// 检查连接状态 -bool check_connection(MQTTClient client) -{ - pthread_mutex_lock(&connect_mutex); - int state = MQTTClient_isConnected(client); - is_connected = (state == 1); - pthread_mutex_unlock(&connect_mutex); - return is_connected; -} - -// 设置连接状态 -void set_connected(bool connected) -{ - pthread_mutex_lock(&connect_mutex); - is_connected = connected; - pthread_mutex_unlock(&connect_mutex); -} - -// 重连函数 -bool reconnect_client(MQTTClient *client) -{ - MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer; - conn_opts.keepAliveInterval = 20; - conn_opts.cleansession = 1; - conn_opts.username = g_conf.user.c_str(); - conn_opts.password = g_conf.password.c_str(); - - int rc; - // 尝试重连,最多尝试5次 - for (int i = 0; i < 5; ++i) - { - std::cerr << "[MQTT] Reconnecting... (attempt " << i + 1 << "/5)" << std::endl; - rc = MQTTClient_connect(*client, &conn_opts); - if (rc == MQTTCLIENT_SUCCESS) - { - set_connected(true); - std::cout << "[MQTT] Reconnected successfully" << std::endl; - return true; - } - std::cerr << "[MQTT] Reconnect failed, rc=" << rc << ". Retrying in " - << g_conf.reconnect_interval << "ms..." << std::endl; - usleep(g_conf.reconnect_interval * 1000); - } - return false; -} - -void *mqtt_pub_gps(void *arg) -{ - (void)arg; - MQTTClient client = nullptr; - MQTTClient_deliveryToken token_d_m; - int rc; - - // 初始化客户端 - if ((rc = MQTTClient_create(&client, - g_conf.address.c_str(), - g_conf.client_id.c_str(), - MQTTCLIENT_PERSISTENCE_NONE, - nullptr)) != MQTTCLIENT_SUCCESS) - { - std::cerr << "Failed to create client, rc=" << rc << std::endl; - return nullptr; - } - - // 初始连接 - if (!reconnect_client(&client)) - { - std::cerr << "[MQTT] Failed to establish initial connection" << std::endl; - MQTTClient_destroy(&client); - return nullptr; - } - - MQTTClient_message pubmsg = MQTTClient_message_initializer; - pubmsg.qos = g_conf.qos; - pubmsg.retained = 0; - - Json::Value root_st; - Json::FastWriter json_writer; - unsigned char msg_st[256] = {0}; - - while (true) - { - // 检查连接状态,断开则尝试重连 - if (!check_connection(client)) - { - std::cerr << "[MQTT] Connection lost. Attempting to reconnect..." << std::endl; - - // 先断开旧连接 - MQTTClient_disconnect(client, 1000); - - // 重连失败则销毁客户端重新创建 - if (!reconnect_client(&client)) - { - std::cerr << "[MQTT] All reconnection attempts failed. Recreating client..." << std::endl; - MQTTClient_destroy(&client); - - // 重新创建客户端 - if ((rc = MQTTClient_create(&client, - g_conf.address.c_str(), - g_conf.client_id.c_str(), - MQTTCLIENT_PERSISTENCE_NONE, - nullptr)) != MQTTCLIENT_SUCCESS) - { - std::cerr << "Failed to recreate client, rc=" << rc << std::endl; - usleep(g_conf.reconnect_interval * 1000); - continue; - } - - // 再次尝试连接 - if (!reconnect_client(&client)) - { - usleep(g_conf.reconnect_interval * 1000); - continue; - } - } - } - - root_st.clear(); - - root_st["lng"] = [&] - { std::ostringstream s; s<( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - - std::string json_string = json_writer.write(root_st); - memcpy(msg_st, json_string.c_str(), json_string.size()); - pubmsg.payload = msg_st; - pubmsg.payloadlen = static_cast(json_string.size()); - - // 发布消息 - if (check_connection(client)) - { - rc = MQTTClient_publishMessage(client, - g_conf.pub_gps_topic.c_str(), - &pubmsg, - &token_d_m); - if (rc == MQTTCLIENT_SUCCESS) - { - // std::cout << "[MQTT] Published to topic: " << g_conf.pub_gps_topic - // << "\n msg: " << json_string << std::endl; - MQTTClient_waitForCompletion(client, token_d_m, g_conf.timeout_ms); - } - else - { - std::cerr << "[MQTT] publish failed, rc=" << rc << std::endl; - set_connected(false); // 发布失败标记为断开连接 - } - } - - usleep(200000); // 200 ms - } - - // 清理资源 - MQTTClient_disconnect(client, 10000); - MQTTClient_destroy(&client); - pthread_mutex_destroy(&connect_mutex); - return nullptr; -} - -class pub_gps_node : public rclcpp::Node -{ -public: - explicit pub_gps_node(const std::string &name) : Node(name) - { - RCLCPP_INFO(this->get_logger(), "%s 节点已启动.", name.c_str()); - gps_subscribe_ = this->create_subscription( - "rtk_message", 10, - std::bind(&pub_gps_node::command_callback, this, std::placeholders::_1)); - } - -private: - void command_callback(const sweeper_interfaces::msg::Rtk::SharedPtr msg) - { - gps_mes.lat = msg->lat; - gps_mes.lng = msg->lon; - gps_mes.course = msg->head; - - if (msg->p_quality == 5) - gps_mes.mode = 2; - else if (msg->p_quality == 4) - gps_mes.mode = 3; - else - gps_mes.mode = msg->p_quality; - } - rclcpp::Subscription::SharedPtr gps_subscribe_; -}; - -std::string generate_mqtt_client_id() -{ - // 获取当前时间戳(以毫秒为单位) - auto now = std::chrono::system_clock::now(); - auto millis = std::chrono::duration_cast(now.time_since_epoch()).count(); - - // 生成一个 4 位随机数 - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1000, 9999); - int random_num = dis(gen); - - // 拼接成 client ID - std::ostringstream oss; - oss << "client_" << millis << "_" << std::setw(4) << std::setfill('0') << random_num; - - return oss.str(); -} - -bool load_config(const std::string &path) -{ - Json::Reader reader; - Json::Value root; - std::ifstream in(path, std::ios::binary); - if (!in.is_open()) - { - std::cerr << "[config] open " << path << " failed\n"; - return false; - } - if (!reader.parse(in, root)) - { - std::cerr << "[config] parse json failed\n"; - return false; - } - - const auto &m = root["mqtt"]; - std::string ip = m["external_net_address"].asString(); // tcp://36.153.162.171 - int port = m["external_net_port"].asInt(); // 19683 - // std::string ip = m["inter_net_address"].asString(); // tcp://192.168.4.196 - // int port = m["inter_net_port"].asInt(); // 11883 - - g_conf.address = ip + ":" + std::to_string(port); - g_conf.client_id = generate_mqtt_client_id(); - g_conf.user = m["mqtt_user"].asString(); - g_conf.password = m["mqtt_password"].asString(); - g_conf.pub_gps_topic = m["pub_gps_topic"].asString(); - - // 从配置读取重连间隔,默认5000ms - if (m.isMember("reconnect_interval")) - { - g_conf.reconnect_interval = m["reconnect_interval"].asInt(); - } - - return true; -} - -int main(int argc, char **argv) -{ - if (!load_config("config.json")) - return -1; - - // 初始化互斥锁 - pthread_mutex_init(&connect_mutex, nullptr); - - pthread_t mqtt_thread; - pthread_create(&mqtt_thread, nullptr, mqtt_pub_gps, nullptr); - - rclcpp::init(argc, argv); - rclcpp::spin(std::make_shared("pub_gps_node")); - rclcpp::shutdown(); - - // 清理资源 - pthread_mutex_destroy(&connect_mutex); - return 0; -} \ No newline at end of file