Skip to content

Commit

Permalink
Prepare 0.4.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
squidfunk committed Dec 16, 2015
1 parent ccde962 commit 3f2b7f8
Show file tree
Hide file tree
Showing 13 changed files with 596 additions and 75 deletions.
17 changes: 15 additions & 2 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
protobluff-0.x.x
protobluff-0.4.0 (2015-12-16)

In progress.
This release adds full support for packed fields (in lite and full runtime).
Furthermore, some functions have been deprecated to prepare for the 1.0.0
release, in particular raw pointer access, because unaligned access of floats
and doubles may cause undefined behavior on some architectures, and the
position of the cursor, as due to the possible erasure of fields during a
cursor's lifetime, the position may not be accurately determined.

Again, this release is mostly compatible with prior versions, but a few
breaking changes to the ABI could not be omitted. See the MIGRATION file for
further assistance. However, approaching the 1.0.0 release, the ABI can be
considered stable very soon. The libtool version has been updated to 3.0.0.

Runtime:

* Deprecated raw pointer access (will be removed in 1.0.0)
* Deprecated pb_cursor_pos() (will be removed in 1.0.0)
* Fixed invalid reads reported when compiling with -fsanitize
* Fixed incorrectly reported position in pb_cursor_seek()
* Fixed cursor state when erasing the last field in a message
* Fixed alignment issues and checks after erasing parts
* Added support for packed fields
* Added missing error string for PB_ERROR_EOM (could have caused segfault)
* Added tests for packed fields
Expand Down
24 changes: 24 additions & 0 deletions MIGRATION
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
0.3.x => 0.4.0

Encoder

In order to handle packed fields, the encoder does now take a fourth
argument, namely the amount of values to be encoded. This is a prerequisite
for the support of packed fields. Now, multiple values can be encoded all
at once, regardless of whether a field is packed or not. This also applies
for messages, which have already been implemented as nested encoders.

This makes it necessary to regenerate the bindings and change all accessors
that write values to repeated fields.

< 0.4.0:

pb_encoder_t person = person_encoder_create(...);
person_encode_phone(&person, &phonenumbers[0]);
person_encode_phone(&person, &phonenumbers[1]);

= 0.4.0:

pb_encoder_t person = person_encoder_create(...);
person_encode_phone(&person, &phonenumbers, 2);

0.2.x => 0.3.0

Binaries
Expand Down
23 changes: 7 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ journal. If no alterations that change the size of the underlying journal are
expected, the journal can be used in *zero-copy mode*, omitting all dynamic
allocations.

Updates on fixed-sized wire types on little-endian machines can be carried out
in-place using raw-pointers to the underlying data. These include the native
Protocol Buffers types `fixed(32|64)`, `sfixed(32|64)`, `float` and `double`
(see the [Protocol Buffers Encoding Guide][] for more information). Strings may
also be accessed through raw-pointers, however writing a string of different
length may result in garbled data, and is thus not recommended.

## Installation

### Building from source
Expand Down Expand Up @@ -197,21 +190,19 @@ PKG_CHECK_MODULES([protobluff], [protobluff])
7. Imports
8. Packages
9. Extensions and nested extensions
10. Deprecation warnings
10. Deprecations for messages, fields, enums and enum values
11. Packed fields

### Not yet supported

1. Packed fields
2. Oneofs
1. Oneofs
2. proto3 support
3. Services (using gRPC and/or ZMQ)
4. Groups (unsure)
5. General proto3 support (unsure)

### Roadmap

1. Oneofs
2. Packed fields
3. Services
These features will be implemented in the order presented. protobluff is
basically compatible with proto3, as proto2 is binary compatible, but some
special types like maps and the Any type need to be implemented.

## License

Expand Down
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

AC_PREREQ(2.69)

AC_INIT([protobluff], [0.3.0], [martin.donath@squidfunk.com])
AC_INIT([protobluff], [0.4.0], [martin.donath@squidfunk.com])
AM_INIT_AUTOMAKE([subdir-objects foreign])

m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
Expand All @@ -48,7 +48,7 @@ AC_CONFIG_MACRO_DIR([m4])

# Library versioning as <current:revision:age> - also remember to synchronize
# this value with the version info in the core/common.h header file.
AC_SUBST([VERSION_INFO], [2:0:0])
AC_SUBST([VERSION_INFO], [3:0:0])

# Checks for programs
AC_PROG_AWK
Expand Down
2 changes: 1 addition & 1 deletion include/protobluff/core/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* Current ABI version as a single integer to test binary compatibility in
* the generated header files: current * 10^6 + revision * 10^3 + age
*/
#define PB_VERSION (2 * 1000000) + (0 * 1000) + 0
#define PB_VERSION (3 * 1000000) + (0 * 1000) + 0

/*
* Agnostic C-linkage classifier for extern functions when compiling from C++
Expand Down
1 change: 1 addition & 0 deletions include/protobluff/message/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ pb_cursor_descriptor(const pb_cursor_t *cursor) {
* \param[in] cursor Cursor
* \return Current position
*/
PB_DEPRECATED
PB_INLINE size_t
pb_cursor_pos(const pb_cursor_t *cursor) {
assert(cursor);
Expand Down
19 changes: 10 additions & 9 deletions src/message/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,18 @@ next(pb_cursor_t *cursor) {
}

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

/* Cleanup and invalidate cursor */
pb_buffer_destroy(&buffer);
pb_stream_destroy(&stream);
if (!cursor->error)
/* 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;
}

Expand Down Expand Up @@ -289,7 +291,7 @@ pb_cursor_next(pb_cursor_t *cursor) {
assert(cursor);
int result = 0;
if (pb_cursor_valid(cursor)) {
cursor->error = pb_cursor_align(cursor);
pb_cursor_align(cursor);
do {
result = cursor->current.packed.end
? next_packed(cursor)
Expand Down Expand Up @@ -531,9 +533,8 @@ pb_cursor_align(pb_cursor_t *cursor) {
assert(pb_cursor_valid(cursor));
pb_error_t error = PB_ERROR_NONE;

/* Check, if current part is already aligned */
const pb_part_t *part = pb_message_part(&(cursor->message));
if (unlikely_(!pb_part_aligned(part))) {
/* Check, if cursor is already aligned */
if (unlikely_(!pb_cursor_aligned(cursor))) {
pb_version_t version = pb_cursor_version(cursor);

/* Align current packed context offset, if given */
Expand Down
13 changes: 12 additions & 1 deletion src/message/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ pb_cursor_create_internal(
pb_message_t *message, /* Message */
pb_tag_t tag); /* Tag */

PB_WARN_UNUSED_RESULT
extern pb_error_t
pb_cursor_align(
pb_cursor_t *cursor); /* Cursor */
Expand Down Expand Up @@ -129,6 +128,18 @@ pb_cursor_version(const pb_cursor_t *cursor) {
return pb_message_version(&(cursor->message));
}

/*!
* Test whether a cursor is properly aligned.
*
* \param[in] cursor Cursor
* \return Test result
*/
PB_INLINE int
pb_cursor_aligned(const pb_cursor_t *cursor) {
assert(cursor);
return pb_message_aligned(&(cursor->message));
}

/*!
* Retrieve the offsets at the current position of a cursor.
*
Expand Down
42 changes: 27 additions & 15 deletions src/message/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,33 @@ pb_field_version(const pb_field_t *field) {
return pb_part_version(&(field->part));
}

/*!
* Test whether a field is properly aligned.
*
* \param[in] field Field
* \return Test result
*/
PB_INLINE int
pb_field_aligned(const pb_field_t *field) {
assert(field);
return pb_part_aligned(&(field->part));
}

/*!
* Ensure that a field is properly aligned.
*
* \param[in,out] field Field
* \return Error code
*/
PB_WARN_UNUSED_RESULT
PB_INLINE pb_error_t
pb_field_align(pb_field_t *field) {
assert(field);
return !pb_part_aligned(&(field->part))
? pb_part_align(&(field->part))
: PB_ERROR_NONE;
}

/*!
* Retrieve the start offset of a field within its underlying journal.
*
Expand Down Expand Up @@ -147,21 +174,6 @@ pb_field_empty(const pb_field_t *field) {
return pb_part_empty(&(field->part));
}

/*!
* Ensure that a field is properly aligned.
*
* \param[in,out] field Field
* \return Error code
*/
PB_WARN_UNUSED_RESULT
PB_INLINE pb_error_t
pb_field_align(pb_field_t *field) {
assert(field);
return !pb_part_aligned(&(field->part))
? pb_part_align(&(field->part))
: PB_ERROR_NONE;
}

/* ------------------------------------------------------------------------- */

/*!
Expand Down
5 changes: 5 additions & 0 deletions src/message/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,11 @@ pb_journal_align(
if (entry->origin >= offset->start) {
offset->end += entry->delta;

/* Current part is a packed field: invalidate */
if (offset->diff.origin && !offset->diff.tag &&
offset->start == offset->end)
invalid = 1;

/* Current part was cleared: clear */
} else if ((offset->start + offset->diff.origin) -
(offset->end + entry->delta) == 0) {
Expand Down
42 changes: 27 additions & 15 deletions src/message/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,33 @@ pb_message_version(const pb_message_t *message) {
return pb_part_version(&(message->part));
}

/*!
* Test whether a message is properly aligned.
*
* \param[in] message Message
* \return Test result
*/
PB_INLINE int
pb_message_aligned(const pb_message_t *message) {
assert(message);
return pb_part_aligned(&(message->part));
}

/*!
* Ensure that a message is properly aligned.
*
* \param[in,out] message Message
* \return Error code
*/
PB_WARN_UNUSED_RESULT
PB_INLINE pb_error_t
pb_message_align(pb_message_t *message) {
assert(message);
return !pb_part_aligned(&(message->part))
? pb_part_align(&(message->part))
: PB_ERROR_NONE;
}

/*!
* Retrieve the start offset of a message within its underlying journal.
*
Expand Down Expand Up @@ -137,21 +164,6 @@ pb_message_empty(const pb_message_t *message) {
return pb_part_empty(&(message->part));
}

/*!
* Ensure that a message is properly aligned.
*
* \param[in,out] message Message
* \return Error code
*/
PB_WARN_UNUSED_RESULT
PB_INLINE pb_error_t
pb_message_align(pb_message_t *message) {
assert(message);
return !pb_part_aligned(&(message->part))
? pb_part_align(&(message->part))
: PB_ERROR_NONE;
}

/* ------------------------------------------------------------------------- */

/*!
Expand Down
24 changes: 15 additions & 9 deletions src/message/part.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ adjust_recursive(pb_part_t *part, pb_stream_t *stream, ptrdiff_t *delta) {
temp.offset.end += *delta;

/* If a tag is given, we're not inside a packed field */
if (part->offset.diff.tag) {
if (part->offset.diff.tag || (
part->offset.start + part->offset.diff.origin >
temp.offset.start + temp.offset.diff.origin)) {

/* The parts don't match, so recurse */
if (temp.offset.start != part->offset.start ||
Expand All @@ -185,8 +187,7 @@ adjust_recursive(pb_part_t *part, pb_stream_t *stream, ptrdiff_t *delta) {
break; /* LCOV_EXCL_LINE */

/* Parts may be unaligned due to length prefix update */
if ((!pb_part_aligned(part) && (error = pb_part_align(part))) ||
(!pb_part_aligned(&temp) && (error = pb_part_align(&temp))))
if (!pb_part_aligned(&temp) && (error = pb_part_align(&temp)))
break; /* LCOV_EXCL_LINE */
}

Expand All @@ -199,10 +200,8 @@ adjust_recursive(pb_part_t *part, pb_stream_t *stream, ptrdiff_t *delta) {
break;
}

/* Adjust length prefix and ensure aligned part */
/* Adjust length prefix */
error = adjust_prefix(&temp, delta);
if (!error && !pb_part_aligned(part))
error = pb_part_align(part);
break;

/* Otherwise just skip stream part */
Expand Down Expand Up @@ -528,6 +527,10 @@ pb_part_write(pb_part_t *part, const uint8_t data[], size_t size) {
error = adjust_prefix(part, &delta);
if (!error)
error = adjust(part, delta);

/* Ensure aligned part */
if (!error && !pb_part_aligned(part))
error = pb_part_align(part);
}
}
return error;
Expand Down Expand Up @@ -561,9 +564,12 @@ pb_part_clear(pb_part_t *part) {
/* Update offsets if necessary */
if (delta) {
part->version++;
part->offset.start = delta + part->offset.end;
part->offset.end += delta;
part->offset.diff.origin = 0;
part->offset.start = delta + part->offset.end;
part->offset.end += delta;

/* Reset origin for non-packed fields */
if (part->offset.diff.tag)
part->offset.diff.origin = 0;

/* Recursive length prefix update of parent messages */
error = adjust(part, delta);
Expand Down
Loading

0 comments on commit 3f2b7f8

Please sign in to comment.