static char *test_trim(void *context) { qd_iterator_t *iter = qd_iterator_string("testing.trim", ITER_VIEW_ALL); qd_iterator_trim_view(iter, 7); if (!qd_iterator_equal(iter, (unsigned char*) "testing")) return "Trim on ITER_VIEW_ALL failed (1)"; qd_iterator_reset_view(iter, ITER_VIEW_ALL); if (!qd_iterator_equal(iter, (unsigned char*) "testing.trim")) return "Trim on ITER_VIEW_ALL failed (2)"; qd_iterator_advance(iter, 4); qd_iterator_trim_view(iter, 5); if (!qd_iterator_equal(iter, (unsigned char*) "ing.t")) return "Trim on ITER_VIEW_ALL failed (3)"; qd_iterator_reset_view(iter, ITER_VIEW_ADDRESS_HASH); qd_iterator_trim_view(iter, 9); if (!qd_iterator_equal(iter, (unsigned char*) "M0testing")) return "Trim on ITER_VIEW_ADDRESS_HASH failed"; qd_iterator_reset(iter); qd_iterator_annotate_space(iter, "my_space.", 9); qd_iterator_trim_view(iter, 18); if (!qd_iterator_equal(iter, (unsigned char*) "M0my_space.testing")) return "Trim on ITER_VIEW_ADDRESS_HASH (with space 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 10); if (!qd_iterator_equal(iter, (unsigned char*) "M0my_space")) return "Trim on ITER_VIEW_ADDRESS_HASH (in space 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 2); if (!qd_iterator_equal(iter, (unsigned char*) "M0")) return "Trim on ITER_VIEW_ADDRESS_HASH (in annotation 1) failed"; qd_iterator_reset(iter); qd_iterator_trim_view(iter, 1); if (!qd_iterator_equal(iter, (unsigned char*) "M")) return "Trim on ITER_VIEW_ADDRESS_HASH (in annotation 2) failed"; qd_iterator_free(iter); return 0; }
static char *test_sub_iterator(void *context) { qd_iterator_t *iter = qd_iterator_string("test_sub_iterator", ITER_VIEW_ALL); qd_iterator_t *sub1 = qd_iterator_sub(iter, qd_iterator_remaining(iter)); qd_iterator_advance(iter, 5); qd_iterator_t *sub2 = qd_iterator_sub(iter, qd_iterator_remaining(iter)); qd_iterator_t *sub3 = qd_iterator_sub(iter, 3); if (!qd_iterator_equal(sub1, (unsigned char*) "test_sub_iterator")) return "Sub Iterator failed - 1"; if (!qd_iterator_equal(sub2, (unsigned char*) "sub_iterator")) return "Sub Iterator failed - 2"; if (!qd_iterator_equal(sub3, (unsigned char*) "sub")) return "Sub Iterator failed - 3"; qd_iterator_free(iter); qd_iterator_free(sub1); qd_iterator_free(sub2); qd_iterator_free(sub3); return 0; }
static qd_parsed_field_t *qd_parse_internal(qd_iterator_t *iter, qd_parsed_field_t *p) { qd_parsed_field_t *field = new_qd_parsed_field_t(); if (!field) return 0; DEQ_ITEM_INIT(field); DEQ_INIT(field->children); field->parent = p; field->raw_iter = 0; field->typed_iter = qd_iterator_dup(iter); uint32_t size = 0; uint32_t count = 0; uint32_t length_of_count = 0; uint32_t length_of_size = 0; field->parse_error = get_type_info(iter, &field->tag, &size, &count, &length_of_size, &length_of_count); if (!field->parse_error) { qd_iterator_trim_view(field->typed_iter, size + length_of_size + 1); // + 1 accounts for the tag length field->raw_iter = qd_iterator_sub(iter, size - length_of_count); qd_iterator_advance(iter, size - length_of_count); for (uint32_t idx = 0; idx < count; idx++) { qd_parsed_field_t *child = qd_parse_internal(field->raw_iter, field); DEQ_INSERT_TAIL(field->children, child); if (!qd_parse_ok(child)) { field->parse_error = child->parse_error; break; } } } return field; }
const char *qd_parse_turbo(qd_iterator_t *iter, qd_parsed_turbo_list_t *annos, uint32_t *user_entries, uint32_t *user_bytes) { if (!iter || !annos || !user_entries || !user_bytes) return "missing argument"; DEQ_INIT(*annos); *user_entries = 0; *user_bytes = 0; // The iter is addressing the message-annotations map. // Open the field describing the map's items uint8_t tag = 0; uint32_t size = 0; uint32_t count = 0; uint32_t length_of_count = 0; uint32_t length_of_size = 0; const char * parse_error = get_type_info(iter, &tag, &size, &count, &length_of_size, &length_of_count); if (parse_error) return parse_error; if (count == 0) return 0; int n_allocs = 0; // Do skeletal parse of each map element for (uint32_t idx = 0; idx < count; idx++) { qd_parsed_turbo_t *turbo; if (n_allocs < QD_MA_FILTER_LEN * 2) { turbo = new_qd_parsed_turbo_t(); n_allocs++; } else { // Retire an existing element. // If there are this many in the list then this one cannot be a // router annotation and must be a user annotation. turbo = DEQ_HEAD(*annos); *user_entries += 1; *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size; DEQ_REMOVE_HEAD(*annos); } if (!turbo) return "failed to allocate qd_parsed_turbo_t"; ZERO(turbo); // Get the buffer pointers for the map element qd_iterator_get_view_cursor(iter, &turbo->bufptr); // Get description of the map element parse_error = get_type_info(iter, &turbo->tag, &turbo->size, &turbo->count, &turbo->length_of_size, &turbo->length_of_count); if (parse_error) { return parse_error; } // Save parsed element DEQ_INSERT_TAIL(*annos, turbo); // Advance map iterator to next map element qd_iterator_advance(iter, turbo->size - turbo->length_of_count); } // remove leading annos in the queue if their prefix is not a match and // return them as part of the user annotations for (int idx=0; idx < n_allocs; idx += 2) { qd_parsed_turbo_t *turbo = DEQ_HEAD(*annos); assert(turbo); if (qd_iterator_prefix_ptr(&turbo->bufptr, turbo->length_of_size + 1, QD_MA_PREFIX)) break; // leading anno is a user annotation map key // remove the key and value from the list and accumulate them as user items *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size; DEQ_REMOVE_HEAD(*annos); free_qd_parsed_turbo_t(turbo); turbo = DEQ_HEAD(*annos); assert(turbo); *user_bytes += sizeof(turbo->tag) + turbo->size + turbo->length_of_size; DEQ_REMOVE_HEAD(*annos); free_qd_parsed_turbo_t(turbo); *user_entries += 2; } return parse_error; }