Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 42 additions & 14 deletions src/openzl/common/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@
#include "openzl/zl_data.h" // ZL_DataID
#include "openzl/zl_errors.h" // ZL_Report

typedef struct {
int mId;
int mValue;
} IntMeta;

DECLARE_VECTOR_TYPE(IntMeta)
DECLARE_VECTOR_TYPE(Stream_IntMetadata)

struct Stream_s { // exposed publicly as ZL_Data
ZL_Refcount buffer;
Expand All @@ -33,8 +28,8 @@ struct Stream_s { // exposed publicly as ZL_Data
size_t bufferUsed; // in bytes
ZL_Refcount stringLens; // ZL_Type_string only.
int writeCommitted;
size_t lastCommmited; // tracks the eltCount of most recent commit
VECTOR(IntMeta) intMetas; // Metadata (arbitrary ID+Ints)
size_t lastCommmited; // tracks the eltCount of most recent commit
VECTOR(Stream_IntMetadata) intMetas; // Metadata (arbitrary ID+Ints)
Arena* alloc;
};

Expand Down Expand Up @@ -417,7 +412,7 @@ ZL_Report STREAM_refStreamWithoutRefCount(Stream* s, const Stream* ref)
return ZL_REPORT_ERROR(allocation, "Failed to reserve metadata");
}
for (size_t pos = 0; pos < meta_size; pos++) {
IntMeta e = VECTOR_AT(ref->intMetas, pos);
Stream_IntMetadata e = VECTOR_AT(ref->intMetas, pos);
if (!VECTOR_PUSHBACK(s->intMetas, e)) {
return ZL_REPORT_ERROR(allocation, "Failed to copy metadata");
}
Expand Down Expand Up @@ -1011,7 +1006,7 @@ static ZL_Report STREAM_copyIntMetas(Stream* dst, const Stream* src)
VECTOR_RESERVE(dst->intMetas, meta_size), meta_size, allocation);

for (size_t pos = 0; pos < meta_size; pos++) {
IntMeta e = VECTOR_AT(src->intMetas, pos);
Stream_IntMetadata e = VECTOR_AT(src->intMetas, pos);
ZL_ERR_IF_NOT(VECTOR_PUSHBACK(dst->intMetas, e), allocation);
}

Expand Down Expand Up @@ -1070,12 +1065,12 @@ ZL_Report STREAM_consume(Stream* data, size_t eltCount)
// findIntMeta() :
// @return index of the Int Metadata of provided @id
// @return -1 if not found
static int findIntMeta(VECTOR(IntMeta) m, int id)
static int findIntMeta(VECTOR(Stream_IntMetadata) m, int id)
{
size_t const nbIntMetas = VECTOR_SIZE(m);
// Scan backward, find latest .id if multiple present
for (int pos = (int)nbIntMetas - 1; pos >= 0; pos--) {
if (VECTOR_DATA(m)[pos].mId == id)
if (VECTOR_DATA(m)[pos].id == id)
return pos;
}
// not found
Expand All @@ -1093,7 +1088,9 @@ ZL_Report STREAM_setIntMetadata(Stream* s, int mId, int mValue)
streamParameter_invalid,
"Int Metadata ID already present");
ZL_ERR_IF_NOT(
VECTOR_PUSHBACK(s->intMetas, ((IntMeta){ mId, mValue })),
VECTOR_PUSHBACK(
s->intMetas,
((Stream_IntMetadata){ .id = mId, .value = mValue })),
allocation);
return ZL_returnSuccess();
}
Expand All @@ -1110,10 +1107,41 @@ ZL_IntMetadata STREAM_getIntMetadata(const Stream* s, int mId)
};
return (ZL_IntMetadata){
.isPresent = 1,
.mValue = VECTOR_DATA(s->intMetas)[idx].mValue,
.mValue = VECTOR_DATA(s->intMetas)[idx].value,
};
}

size_t STREAM_numIntMetadata(const Stream* s)
{
ZL_ASSERT_NN(s);
return VECTOR_SIZE(s->intMetas);
}

ZL_Report STREAM_copyIntMetadata(
Stream_IntMetadata* dst,
const Stream* src,
size_t expectedEntries)
{
ZL_RESULT_DECLARE_SCOPE_REPORT(NULL);
ZL_ASSERT_NN(src);
ZL_ERR_IF_NE(
expectedEntries,
VECTOR_SIZE(src->intMetas),
streamParameter_invalid,
"Metadata entry count does not match the stream");
if (expectedEntries == 0) {
return ZL_returnSuccess();
}
ZL_ERR_IF_NULL(
dst,
streamParameter_invalid,
"Metadata destination is NULL for a non-empty stream");
for (size_t i = 0; i < expectedEntries; ++i) {
dst[i] = VECTOR_AT(src->intMetas, i);
}
return ZL_returnSuccess();
}

int STREAM_hasBuffer(const Stream* s)
{
return !ZL_Refcount_null(&s->buffer);
Expand Down
34 changes: 34 additions & 0 deletions src/openzl/common/stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ ZL_BEGIN_C_DECLS
DECLARE_VECTOR_POINTERS_TYPE(ZL_Data)
DECLARE_VECTOR_CONST_POINTERS_TYPE(ZL_Data)

/**
* One integer metadata entry attached to a Stream.
*
* This type is exposed by the internal Stream interface so callers that need
* to snapshot a stream can preserve both the metadata identifier and value.
* The public lookup API returns only the value for a caller-supplied ID.
*/
typedef struct {
/** Identifier passed to STREAM_setIntMetadata(). */
int id;
/** Integer value associated with this entry's identifier. */
int value;
} Stream_IntMetadata;

/**
* Internal Stream interface.
*
Expand Down Expand Up @@ -238,6 +252,26 @@ size_t STREAM_byteCapacity(const Stream* s);
ZL_Report STREAM_setIntMetadata(Stream* s, int mId, int mValue);
ZL_IntMetadata STREAM_getIntMetadata(const Stream* s, int mId);

/** Number of integer metadata entries attached to @p s. */
size_t STREAM_numIntMetadata(const Stream* s);

/**
* Copy every integer metadata entry from @p src into @p dst.
*
* @p dst must have capacity for at least @p expectedEntries entries.
* @p expectedEntries must exactly equal STREAM_numIntMetadata(src). @p dst
* may be NULL only when @p expectedEntries is zero. Invalid arguments return
* an error without modifying @p dst.
*
* Metadata lookup semantics do not depend on entry order. This function
* nevertheless preserves stable stream order, so callers that hash or compare
* the copied representation bytewise will distinguish different orders.
*/
ZL_Report STREAM_copyIntMetadata(
Stream_IntMetadata* dst,
const Stream* src,
size_t expectedEntries);

/**
* Hash the content of all streams provided in @p streams.
* Only meaningful when all streams have been committed.
Expand Down
23 changes: 23 additions & 0 deletions tests/unittest/common/test_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,30 @@ TEST(Stream, intMetadata)
// test what happens when requesting a non-present metadata id
ASSERT_EQ(ZL_Data_getIntMetadata(s, 3).isPresent, 0);

ASSERT_EQ(STREAM_numIntMetadata(s), 2u);
Stream_IntMetadata metadata[2];
ASSERT_ZS_VALID(STREAM_copyIntMetadata(metadata, s, 2));
EXPECT_EQ(metadata[0].id, 1);
EXPECT_EQ(metadata[0].value, 1001);
EXPECT_EQ(metadata[1].id, 2);
EXPECT_EQ(metadata[1].value, 2002);

const Stream_IntMetadata sentinel = { 7, 7007 };
Stream_IntMetadata rejected = sentinel;
EXPECT_TRUE(ZL_isError(STREAM_copyIntMetadata(&rejected, s, 1)));
EXPECT_EQ(rejected.id, sentinel.id);
EXPECT_EQ(rejected.value, sentinel.value);
EXPECT_TRUE(ZL_isError(STREAM_copyIntMetadata(&rejected, s, 3)));
EXPECT_EQ(rejected.id, sentinel.id);
EXPECT_EQ(rejected.value, sentinel.value);
EXPECT_TRUE(ZL_isError(STREAM_copyIntMetadata(nullptr, s, 2)));

STREAM_free(s);

ZL_Data* const empty = STREAM_create(kZeroID);
ASSERT_NE(empty, nullptr);
EXPECT_ZS_VALID(STREAM_copyIntMetadata(nullptr, empty, 0));
STREAM_free(empty);
}

// check byteSize function
Expand Down
Loading