static gint dissect_parameter_sequence(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
    gint offset, const guint encoding, guint size, const char *label,
    guint16 version, guint32 *pStatusInfo, guint16 vendor_id,
    gboolean is_inline_qos, coherent_set_entity_info *coherent_set_entity_info_object) {

  proto_item *ti, *param_item, *param_len_item = NULL;
  proto_tree *rtps_parameter_sequence_tree, *rtps_parameter_tree;
  guint32    parameter, param_length, param_length_length = 2;
  gint       original_offset = offset, initial_offset = offset;
  type_mapping * type_mapping_object = NULL;
  const gchar * param_name = NULL;
  if (!pinfo->fd->visited) {
    /*
     * At minimum, type_mapping_object->fields_visited must be
     * initialized to 0, because we haven't visited any fields
     * yet.  The routines that visit fields just set individual
     * bits in type_mapping_object->fields_visited; they don't
     * initialize it.
     */
    type_mapping_object = wmem_new(wmem_file_scope(), type_mapping);
    type_mapping_object->fields_visited = 0;
    type_mapping_object->guid.fields_present = 0;
  }

  rtps_parameter_sequence_tree = proto_tree_add_subtree_format(tree, tvb, offset, size,
          ett_rtps_parameter_sequence, &ti, "%s:", label);

  /* Loop through all the parameters defined until PID_SENTINEL is found */
  for (;;) {
    size -= offset - original_offset;
    if (size < 4) {
      expert_add_info_format(pinfo, (param_len_item == NULL) ? ti : param_len_item,
              &ei_rtps_parameter_value_invalid, "ERROR: not enough bytes to read the next parameter");
      return 0;
    }
    original_offset = offset;

    /* Reads parameter and create the sub tree. At this point we don't know
     * the final string that will identify the node or its length. It will
     * be set later...
     */
    parameter = tvb_get_guint16(tvb, offset, encoding);
    param_length = tvb_get_guint16(tvb, offset+2, encoding);
    if ((parameter & PID_EXTENDED) == PID_EXTENDED) {
      offset += 4;
      /* get extended member id and length */
      parameter = tvb_get_guint32(tvb, offset, encoding);
      param_length = tvb_get_guint32(tvb, offset+4, encoding);
      param_length_length = 4;
    }
    if (version < 0x0200) {
      rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                        ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_vals, "Unknown (0x%04x)"));

      proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id, tvb, offset, 2, parameter);
    } else {
      gboolean goto_default = TRUE;
      switch(vendor_id) {
        case RTPS_VENDOR_RTI_DDS:
        case RTPS_VENDOR_RTI_DDS_MICRO: {
          if (is_inline_qos) {
            param_name = try_val_to_str(parameter, parameter_id_inline_qos_rti);
            if (param_name != NULL) {
              rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_inline_qos_rti, "Unknown (0x%04x)"));
              proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_inline_rti, tvb, offset,
                      param_length_length, parameter);
              goto_default = FALSE;
            }
          } else {
            param_name = try_val_to_str(parameter, parameter_id_rti_vals);
            if (param_name != NULL) {
              rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                        ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_rti_vals, "Unknown (0x%04x)"));
              proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_rti, tvb, offset,
                      param_length_length, parameter);
              goto_default = FALSE;
            }
          }
          break;
        }
        case RTPS_VENDOR_TOC: {
          param_name = try_val_to_str(parameter, parameter_id_toc_vals);
          if (param_name != NULL) {
            rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                  ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_toc_vals, "Unknown (0x%04x)"));

            proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_toc, tvb, offset,
                    param_length_length, parameter);
            goto_default = FALSE;
          }
          break;
        }
        case RTPS_VENDOR_ADL_DDS: {
          param_name = try_val_to_str(parameter, parameter_id_adl_vals);
          if (param_name != NULL) {
            rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                  ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_adl_vals, "Unknown (0x%04x)"));

            proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_adl, tvb, offset,
                    param_length_length, parameter);
            goto_default = FALSE;
          }
          break;
        }
      }
      if (goto_default) {
        rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
            ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_v2_vals, "Unknown (0x%04x)"));
        proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_v2, tvb, offset,
                param_length_length, parameter);
      }

    }
    /* after param_id */
    offset += param_length_length;

    if (parameter == PID_SENTINEL) {
      /* PID_SENTINEL closes the parameter list, (length is ignored) */
      proto_item_set_len(param_item, 4);
      offset += 2;
      proto_item_set_len(rtps_parameter_sequence_tree, offset - initial_offset);
      return offset;
    }

    /* parameter length */
    param_len_item = proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_length,
                        tvb, offset, param_length_length, encoding);
    offset += param_length_length;

    /* Make sure we have enough bytes for the param value */
    if ((size-4 < param_length) &&
        (parameter != PID_SENTINEL)) {
      expert_add_info_format(pinfo, param_len_item, &ei_rtps_parameter_value_invalid, "Not enough bytes to read the parameter value");
      return 0;
    }

    /* Sets the end of this item (now we know it!) */
    proto_item_set_len(param_item, param_length+2*param_length_length);

    /* This way, we can include vendor specific dissections without modifying the main ones */

      if (!dissect_parameter_sequence_v1(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item,
        offset, encoding, size, param_length, parameter, version, type_mapping_object, coherent_set_entity_info_object)) {
          if ((version < 0x0200) ||
            !dissect_parameter_sequence_v2(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item,
            offset, encoding, param_length, parameter,
            pStatusInfo, vendor_id, type_mapping_object)) {
              if (param_length > 0) {
                proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_data, tvb,
                        offset, param_length, ENC_NA);
              }
          }
      }

    switch (vendor_id) {
      case RTPS_VENDOR_RTI_DDS:
      case RTPS_VENDOR_RTI_DDS_MICRO: {
        dissect_parameter_sequence_rti_dds(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter, type_mapping_object, is_inline_qos, vendor_id);
        break;
      }
      case RTPS_VENDOR_TOC: {
        dissect_parameter_sequence_toc(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter);
        break;
      }
      case RTPS_VENDOR_ADL_DDS: {
        dissect_parameter_sequence_adl(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter);
        break;
      }
      default:
        break;
    }

    rtps_util_insert_type_mapping_in_registry(pinfo, type_mapping_object);
    offset += param_length;
  }
  proto_item_set_len(ti, offset - initial_offset);
  return offset;
}
static gint dissect_parameter_sequence(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
    gint offset, const guint encoding, guint size, const char *label,
    guint16 version, guint32 *pStatusInfo, guint16 vendor_id,
    gboolean is_inline_qos, coherent_set_entity_info *coherent_set_entity_info_object) {

  proto_item *ti, *param_item, *param_len_item = NULL;
  proto_tree *rtps_parameter_sequence_tree, *rtps_parameter_tree;
  guint32    parameter, param_length, param_length_length = 2;
  gint       original_offset = offset, initial_offset = offset;
  type_mapping * type_mapping_object = NULL;
  const gchar * param_name = NULL;
  if (!pinfo->fd->visited) {
     
    type_mapping_object = wmem_new(wmem_file_scope(), type_mapping);
    type_mapping_object->fields_visited = 0;
    type_mapping_object->guid.fields_present = 0;
  }

  rtps_parameter_sequence_tree = proto_tree_add_subtree_format(tree, tvb, offset, size,
          ett_rtps_parameter_sequence, &ti, "%s:", label);

   
  for (;;) {
    size -= offset - original_offset;
    if (size < 4) {
      expert_add_info_format(pinfo, (param_len_item == NULL) ? ti : param_len_item,
              &ei_rtps_parameter_value_invalid, "ERROR: not enough bytes to read the next parameter");
      return 0;
    }
    original_offset = offset;

     
    parameter = tvb_get_guint16(tvb, offset, encoding);
    param_length = tvb_get_guint16(tvb, offset+2, encoding);
    if ((parameter & PID_EXTENDED) == PID_EXTENDED) {
      offset += 4;
       
      parameter = tvb_get_guint32(tvb, offset, encoding);
      param_length = tvb_get_guint32(tvb, offset+4, encoding);
      param_length_length = 4;
    }
    if (version < 0x0200) {
      rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                        ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_vals, "Unknown (0x%04x)"));

      proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id, tvb, offset, 2, parameter);
    } else {
      gboolean goto_default = TRUE;
      switch(vendor_id) {
        case RTPS_VENDOR_RTI_DDS:
        case RTPS_VENDOR_RTI_DDS_MICRO: {
          if (is_inline_qos) {
            param_name = try_val_to_str(parameter, parameter_id_inline_qos_rti);
            if (param_name != NULL) {
              rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_inline_qos_rti, "Unknown (0x%04x)"));
              proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_inline_rti, tvb, offset,
                      param_length_length, parameter);
              goto_default = FALSE;
            }
          } else {
            param_name = try_val_to_str(parameter, parameter_id_rti_vals);
            if (param_name != NULL) {
              rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                        ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_rti_vals, "Unknown (0x%04x)"));
              proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_rti, tvb, offset,
                      param_length_length, parameter);
              goto_default = FALSE;
            }
          }
          break;
        }
        case RTPS_VENDOR_TOC: {
          param_name = try_val_to_str(parameter, parameter_id_toc_vals);
          if (param_name != NULL) {
            rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                  ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_toc_vals, "Unknown (0x%04x)"));

            proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_toc, tvb, offset,
                    param_length_length, parameter);
            goto_default = FALSE;
          }
          break;
        }
        case RTPS_VENDOR_ADL_DDS: {
          param_name = try_val_to_str(parameter, parameter_id_adl_vals);
          if (param_name != NULL) {
            rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
                  ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_adl_vals, "Unknown (0x%04x)"));

            proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_adl, tvb, offset,
                    param_length_length, parameter);
            goto_default = FALSE;
          }
          break;
        }
      }
      if (goto_default) {
        rtps_parameter_tree = proto_tree_add_subtree(rtps_parameter_sequence_tree, tvb, offset, -1,
            ett_rtps_parameter, &param_item, val_to_str(parameter, parameter_id_v2_vals, "Unknown (0x%04x)"));
        proto_tree_add_uint(rtps_parameter_tree, hf_rtps_parameter_id_v2, tvb, offset,
                param_length_length, parameter);
      }

    }
     
    offset += param_length_length;

    if (parameter == PID_SENTINEL) {
       
      proto_item_set_len(param_item, 4);
      offset += 2;
      proto_item_set_len(rtps_parameter_sequence_tree, offset - initial_offset);
      return offset;
    }

     
    param_len_item = proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_length,
                        tvb, offset, param_length_length, encoding);
    offset += param_length_length;

     
    if ((size-4 < param_length) &&
        (parameter != PID_SENTINEL)) {
      expert_add_info_format(pinfo, param_len_item, &ei_rtps_parameter_value_invalid, "Not enough bytes to read the parameter value");
      return 0;
    }

     
    proto_item_set_len(param_item, param_length+2*param_length_length);

     

      if (!dissect_parameter_sequence_v1(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item,
        offset, encoding, size, param_length, parameter, version, type_mapping_object, coherent_set_entity_info_object)) {
          if ((version < 0x0200) ||
            !dissect_parameter_sequence_v2(rtps_parameter_tree, pinfo, tvb, param_item, param_len_item,
            offset, encoding, param_length, parameter,
            pStatusInfo, vendor_id, type_mapping_object)) {
              if (param_length > 0) {
                proto_tree_add_item(rtps_parameter_tree, hf_rtps_parameter_data, tvb,
                        offset, param_length, ENC_NA);
              }
          }
      }

    switch (vendor_id) {
      case RTPS_VENDOR_RTI_DDS:
      case RTPS_VENDOR_RTI_DDS_MICRO: {
        dissect_parameter_sequence_rti_dds(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter, type_mapping_object, is_inline_qos, vendor_id);
        break;
      }
      case RTPS_VENDOR_TOC: {
        dissect_parameter_sequence_toc(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter);
        break;
      }
      case RTPS_VENDOR_ADL_DDS: {
        dissect_parameter_sequence_adl(rtps_parameter_tree, pinfo, tvb,
            param_item, param_len_item, offset, encoding, param_length, parameter);
        break;
      }
      default:
        break;
    }

    rtps_util_insert_type_mapping_in_registry(pinfo, type_mapping_object);
    offset += param_length;
  }
  proto_item_set_len(ti, offset - initial_offset);
  return offset;
}