コード例 #1
0
ファイル: test.c プロジェクト: squidfunk/protobluff
} END_TEST

/*
 * Create a const-iterator over a oneof descriptor.
 */
START_TEST(test_oneof_iterator) {
  pb_oneof_descriptor_iter_t it =
    pb_oneof_descriptor_iter_create(&oneof_descriptor);

  /* Assert descriptor size */
  fail_if(pb_oneof_descriptor_empty(&oneof_descriptor));
  ck_assert_uint_eq(3, pb_oneof_descriptor_size(&oneof_descriptor));

  /* Walk through descriptor fields forwards */
  fail_unless(pb_oneof_descriptor_iter_begin(&it));
  for (size_t f = 1; f <= 3; f++) {
    const pb_field_descriptor_t *descriptor =
      pb_oneof_descriptor_iter_current(&it);
    ck_assert_uint_eq(f - 1, pb_oneof_descriptor_iter_pos(&it));

    /* Assemble field name */
    char name[5];
    snprintf(name, 5, "F%02d", pb_field_descriptor_tag(descriptor));

    /* Assert field name and tag */
    ck_assert_uint_eq(f, pb_field_descriptor_tag(descriptor));
    fail_if(strcmp(name, pb_field_descriptor_name(descriptor)));

    /* Advance iterator */
    ck_assert_uint_eq(f != 3, pb_oneof_descriptor_iter_next(&it));
  }

  /* Assert descriptor iterator validity */
  fail_if(pb_oneof_descriptor_iter_next(&it));

  /* Walk through descriptor fields backwards */
  fail_unless(pb_oneof_descriptor_iter_end(&it));
  for (size_t f = 3; f >= 1; f--) {
    const pb_field_descriptor_t *descriptor =
      pb_oneof_descriptor_iter_current(&it);
    ck_assert_uint_eq(f - 1, pb_oneof_descriptor_iter_pos(&it));

    /* Assemble field name */
    char name[5];
    snprintf(name, 5, "F%02d", pb_field_descriptor_tag(descriptor));

    /* Assert field name and tag */
    ck_assert_uint_eq(f, pb_field_descriptor_tag(descriptor));
    fail_if(strcmp(name, pb_field_descriptor_name(descriptor)));

    /* Advance iterator */
    ck_assert_uint_eq(f != 1, pb_oneof_descriptor_iter_prev(&it));
  }

  /* Assert descriptor iterator validity again */
  fail_if(pb_oneof_descriptor_iter_prev(&it));

  /* Free all allocated memory */
  pb_oneof_descriptor_iter_destroy(&it);
} END_TEST
コード例 #2
0
ファイル: cursor.c プロジェクト: squidfunk/protobluff
/*!
 * Move a cursor to the next field.
 *
 * \param[in,out] cursor Cursor
 * \return               Test result
 */
static int
next(pb_cursor_t *cursor) {
  assert(cursor);
  pb_offset_t *offset = &(cursor->current.offset),
              *packed = &(cursor->current.packed);

  /* Create temporary buffer to read the next value */
  pb_buffer_t buffer = pb_buffer_create_zero_copy_internal(
    pb_journal_data_from(pb_cursor_journal(cursor), 0),
      pb_message_end(&(cursor->message)));

  /* Create stream over temporary buffer */
  pb_stream_t stream = pb_stream_create_at(&buffer, offset->end);
  while (pb_stream_left(&stream)) {

    /* Adjust offsets */
    offset->start       = offset->end;
    offset->diff.origin = pb_message_start(&(cursor->message));
    offset->diff.tag    = pb_stream_offset(&stream);

    /* Read tag from stream */
    pb_tag_t tag; uint32_t length;
    if ((cursor->error = pb_stream_read(&stream, PB_TYPE_UINT32, &tag)))
      break;

    /* Extract wiretype and tag */
    pb_wiretype_t wiretype = tag & 7;
    tag >>= 3;

    /* Skip field contents to determine length */
    offset->diff.length = pb_stream_offset(&stream);
    if (wiretype == PB_WIRETYPE_LENGTH) {
      if ((cursor->error = pb_stream_read(&stream, PB_TYPE_UINT32, &length)))
        break;
      offset->start = pb_stream_offset(&stream);
      if ((cursor->error = pb_stream_advance(&stream, length)))
        break;
    } else {
      offset->start = pb_stream_offset(&stream);
      if ((cursor->error = pb_stream_skip(&stream, wiretype)))
        break;
    }

    /* Adjust offsets */
    offset->end          = pb_stream_offset(&stream);
    offset->diff.origin -= offset->start;
    offset->diff.tag    -= offset->start;
    offset->diff.length -= offset->start;

    /* If a tag is set check if the tags match or continue */
    if (cursor->tag && cursor->tag != tag) {
      continue;

    /* Otherwise try to load descriptor for current tag */
    } else if (!cursor->current.descriptor ||
        pb_field_descriptor_tag(cursor->current.descriptor) != tag) {
      if (!(cursor->current.descriptor = pb_descriptor_field_by_tag(
          pb_message_descriptor(&(cursor->message)), tag)))
        continue;
    }

    /* Switch to packed context in case of packed field */
    if (wiretype != pb_field_descriptor_wiretype(cursor->current.descriptor) &&
        wiretype == PB_WIRETYPE_LENGTH) {
      *packed = *offset;

      /* Prepare offsets for packed field members */
      offset->end         = offset->start;
      offset->diff.tag    = 0;
      offset->diff.length = 0;
    }

    /* Cleanup and return */
    pb_stream_destroy(&stream);
    pb_buffer_destroy(&buffer);
    return !packed->end;
  }

  /* Invalidate cursor if at end */
  if (!(pb_stream_left(&stream) && cursor->error))
    cursor->error = PB_ERROR_EOM;

  /* Cleanup and return */
  pb_stream_destroy(&stream);
  pb_buffer_destroy(&buffer);
  return 0;
}
コード例 #3
0
ファイル: part.c プロジェクト: zhangjinde/protobluff
/*!
 * Initialize a part.
 *
 * The journal must be tested for writability before writing to the binary, as
 * the binary write is irreversible, while the journal could be reverted.
 *
 * \warning Some lines excluded from code coverage are impossible to occur,
 * but they are necessary to ensure application-wide proper error handling.
 * Others, especially those concerning the journal and binary, are not
 * testable within the context of a part.
 *
 * \param[in,out] part       Part
 * \param[in]     descriptor Field descriptor
 */
static void
init(pb_part_t *part, const pb_field_descriptor_t *descriptor) {
  assert(part && descriptor);
  assert(pb_part_aligned(part));

  /* Initialize field for writing */
  pb_binary_buffer_t buffer = pb_binary_buffer_create();
  do {
    pb_wiretype_t wiretype = pb_field_descriptor_wiretype(descriptor);
    pb_tag_t tag = pb_field_descriptor_tag(descriptor);

    /* Write tag to buffer and backup offsets */
    uint32_t value = wiretype | (tag << 3);
    if (pb_binary_buffer_write_varint32(&buffer, &value))
      break;                                               /* LCOV_EXCL_LINE */
    part->offset.diff.tag    = part->offset.start;
    part->offset.diff.length = part->offset.start
                             + pb_binary_buffer_size(&buffer);

    /* Write default length of zero for length-prefixed fields */
    if (wiretype == PB_WIRETYPE_LENGTH) {
      uint32_t bytes = 0;
      if (pb_binary_buffer_write_varint32(&buffer, &bytes))
        break;                                             /* LCOV_EXCL_LINE */
    }

    /* New data must be written to part, so obtain journal */
    pb_journal_t *journal = pb_binary_journal(part->binary);
    assert(journal);

    /* Write buffer to binary and perform manual alignment */
    pb_error_t error = pb_journal_log(journal,
      part->offset.start + part->offset.diff.origin,
      part->offset.end, pb_binary_buffer_size(&buffer));
    if (!error) {
      size_t offset = pb_binary_buffer_size(&buffer);
      error = pb_binary_write(part->binary,
        part->offset.start, part->offset.end,
          pb_binary_buffer_data(&buffer), pb_binary_buffer_size(&buffer));
      if (unlikely_(error)) {
        pb_journal_revert(journal);                        /* LCOV_EXCL_LINE */

      /* Update offsets */
      } else {                                             /* LCOV_EXCL_LINE */
        part->version++;
        part->offset.start       += offset;
        part->offset.end         += pb_binary_buffer_size(&buffer);
        part->offset.diff.origin -= offset;
        part->offset.diff.tag    -= part->offset.start;
        part->offset.diff.length -= part->offset.start;

        /* Recursive length prefix update of parent messages */
        if (!adjust(part, pb_binary_buffer_size(&buffer))) {
          pb_binary_buffer_destroy(&buffer);
          return;
        }
      }
    }                                                      /* LCOV_EXCL_LINE */
  } while (0);                                             /* LCOV_EXCL_LINE */

  /* Yes. You pulled a Pobert */
  pb_binary_buffer_destroy(&buffer);                       /* LCOV_EXCL_LINE */
  pb_part_invalidate(part);                                /* LCOV_EXCL_LINE */
}