text: /**
   * @file subscriber_topic1_topic2.c
   * @brief Cote Subscriber example in C
   */
  
  
  /******************************************************************************/
  /* Includes                                                                   */
  /******************************************************************************/
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <inttypes.h>
  #include <assert.h>
  #include <signal.h>
  #include <cJSON.h>
  
  #include "cote.h"
  
  
  /******************************************************************************/
  /* Variables                                                                  */
  /******************************************************************************/
  
  static bool terminate = false;                                      /* Flag used to terminate the application */
  
  
  /******************************************************************************/
  /* Prototypes                                                                 */
  /******************************************************************************/
  
  /**
   * @brief Signal hanlder
   * @param signo Signal number
   */
  static void sig_handler(int signo);
  
  /**
   * @brief Callback function invoked when message is received
   * @param cote Cote instance
   * @param topic Topic of the message
   * @param amp AMP message
   * @param user User data
   * @return Always return NULL
   */
  static amp_msg_t *callback(cote_t *cote, char *topic, amp_msg_t *amp, void *user);
  
  
  /******************************************************************************/
  /* Functions                                                                  */
  /******************************************************************************/
  
  /**
   * @brief Main function
   * @param argc Number of arguments
   * @param argv Arguments
   * @return Always returns 0
   */
  int main(int argc, char** argv) {
  
    cote_t *cote;
    
    /* Initialize sig handler */
    signal(SIGINT, sig_handler);
    
    /* Create Cote "pub" instance */
    if (NULL == (cote = cote_create("sub", "subscriber_topic1_topic2"))) {
      printf("unable to create cote instance\n");
      exit(EXIT_FAILURE);
    }
    
    /* Set cote options */
    cJSON *subscribesTo = cJSON_CreateArray();
    if (NULL == subscribesTo) {
      printf("unable to set allocate memory\n");
      cote_release(cote);
      exit(EXIT_FAILURE);
    }
    cJSON *topic1 = cJSON_CreateString("topic1");
    if (NULL == topic1) {
      printf("unable to set allocate memory\n");
      cote_release(cote);
      cJSON_Delete(subscribesTo);
      exit(EXIT_FAILURE);
    }
    cJSON_AddItemToArray(subscribesTo, topic1);
    cJSON *topic2 = cJSON_CreateString("topic2");
    if (NULL == topic2) {
      printf("unable to set allocate memory\n");
      cote_release(cote);
      cJSON_Delete(subscribesTo);
      exit(EXIT_FAILURE);
    }
    cJSON_AddItemToArray(subscribesTo, topic2);
    if (0 != cote_set_option(cote, "subscribesTo", subscribesTo)) {
      printf("unable to set cote subscribesTo option\n");
      cote_release(cote);
      cJSON_Delete(subscribesTo);
      exit(EXIT_FAILURE);
    }
    cJSON_Delete(subscribesTo);
    
    /* Start instance */
    if (0 != cote_start(cote)) {
      printf("unable to start cote instance\n");
      cote_release(cote);
      exit(EXIT_FAILURE);
    }
    
    /* Subscribe to topic1 and topic2 */
    cote_subscribe(cote, "topic1", &callback, NULL);
    cote_subscribe(cote, "topic2", &callback, NULL);
  
    printf("subscriber started\n");
  
    /* Wait before terminating the program */
    while (false == terminate) {
      sleep(1);
    }
  
    /* Release memory */
    cote_release(cote);
  
    return 0;
  }
  
  /**
   * @brief Signal hanlder
   * @param signo Signal number
   */
  static void sig_handler(int signo) {
  
    /* SIGINT handling */
    if (SIGINT == signo) {
      terminate = true;
    }
  }
  
  /**
   * @brief Callback function invoked when message is received
   * @param cote Cote instance
   * @param topic Topic of the message
   * @param amp AMP message
   * @param user User data
   * @return Always return NULL
   */
  static amp_msg_t *callback(cote_t *cote, char *topic, amp_msg_t *amp, void *user) {
  
    (void)cote;
    assert(NULL != topic);
    assert(NULL != amp);
    (void)user;
  
    int64_t bint; char *str;
  
    printf("sub client message received from topic '%s'\n", topic);
  
    /* Parse all fields of the message */
    amp_field_t *field = amp_get_first(amp);
    while (NULL != field) {
    
      /* Switch depending of the type */
      switch (field->type) {
        case AMP_TYPE_BLOB:
          printf("<Buffer");
          for (int index_data = 0; index_data < field->size; index_data++) {
            printf(" %02x", ((unsigned char *)field->data)[index_data]);
          }
          printf(">\n");
          break;
        case AMP_TYPE_STRING:
          printf("%s\n", (char *)field->data);
          break;
        case AMP_TYPE_BIGINT:
          bint = (*(int64_t *)field->data);
          printf("%" PRId64 "\n", bint);
          break;
        case AMP_TYPE_JSON:
          str = cJSON_PrintUnformatted((cJSON *)field->data);
          printf("%s\n", str);
          free(str);
          break;
        default:
          /* Should not occur */
          break;
      }
      
      /* Next field */
      field = amp_get_next(amp);
    }
  
    return NULL;
  }
  