Changeset 04a7435f in mainline for uspace/app/bithenge/blob.c


Ignore:
Timestamp:
2012-06-26T19:56:26Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
978ccaf1
Parents:
f2da0bb
Message:

Bithenge: add the struct transform

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/blob.c

    rf2da0bb r04a7435f  
    296296}
    297297
     298typedef struct {
     299        bithenge_blob_t base;
     300        bithenge_blob_t *source;
     301        aoff64_t offset;
     302        aoff64_t size;
     303        bool size_matters;
     304} subblob_t;
     305
     306static inline subblob_t *blob_as_subblob(bithenge_blob_t *base)
     307{
     308        return (subblob_t *)base;
     309}
     310
     311static inline bithenge_blob_t *subblob_as_blob(subblob_t *blob)
     312{
     313        return &blob->base;
     314}
     315
     316static int subblob_size(bithenge_blob_t *base, aoff64_t *size)
     317{
     318        subblob_t *blob = blob_as_subblob(base);
     319        if (blob->size_matters) {
     320                *size = blob->size;
     321                return EOK;
     322        } else {
     323                int rc = bithenge_blob_size(blob->source, size);
     324                *size -= blob->offset;
     325                return rc;
     326        }
     327}
     328
     329static int subblob_read(bithenge_blob_t *base, aoff64_t offset,
     330    char *buffer, aoff64_t *size)
     331{
     332        subblob_t *blob = blob_as_subblob(base);
     333        if (blob->size_matters) {
     334                if (offset > blob->size)
     335                        return EINVAL;
     336                *size = min(*size, blob->size - offset);
     337        }
     338        offset += blob->offset;
     339        return bithenge_blob_read(blob->source, offset, buffer, size);
     340}
     341
     342static int subblob_destroy(bithenge_blob_t *base)
     343{
     344        subblob_t *blob = blob_as_subblob(base);
     345        bithenge_blob_dec_ref(blob->source);
     346        free(blob);
     347        return EOK;
     348}
     349
     350static const bithenge_random_access_blob_ops_t subblob_ops = {
     351        .size = subblob_size,
     352        .read = subblob_read,
     353        .destroy = subblob_destroy,
     354};
     355
     356static bool is_subblob(bithenge_blob_t *blob)
     357{
     358        return blob->base.blob_ops == &subblob_ops;
     359}
     360
     361static int new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
     362    aoff64_t offset, aoff64_t size, bool size_matters)
     363{
     364        assert(out);
     365        assert(source);
     366        int rc;
     367        subblob_t *blob = 0;
     368
     369        if (is_subblob(source)) {
     370                /* We can do some optimizations this way */
     371                if (!size_matters)
     372                        size = 0;
     373                subblob_t *source_subblob = blob_as_subblob(source);
     374                if (source_subblob->size_matters &&
     375                    offset + size > source_subblob->size) {
     376                        rc = EINVAL;
     377                        goto error;
     378                }
     379
     380                if (source->base.refs == 1) {
     381                        source_subblob->offset += offset;
     382                        source_subblob->size -= offset;
     383                        if (size_matters) {
     384                                source_subblob->size_matters = true;
     385                                source_subblob->size = size;
     386                        }
     387                        *out = bithenge_blob_as_node(source);
     388                        return EOK;
     389                }
     390
     391                if (!size_matters && source_subblob->size_matters) {
     392                        size_matters = true;
     393                        size = source_subblob->size - offset;
     394                }
     395                offset += source_subblob->offset;
     396                source = source_subblob->source;
     397                bithenge_blob_inc_ref(source);
     398                bithenge_blob_dec_ref(subblob_as_blob(source_subblob));
     399        }
     400
     401        blob = malloc(sizeof(*blob));
     402        if (!blob) {
     403                rc = ENOMEM;
     404                goto error;
     405        }
     406        rc = bithenge_new_random_access_blob(subblob_as_blob(blob),
     407            &subblob_ops);
     408        if (rc != EOK)
     409                goto error;
     410        blob->source = source;
     411        blob->offset = offset;
     412        blob->size = size;
     413        blob->size_matters = size_matters;
     414        *out = bithenge_blob_as_node(subblob_as_blob(blob));
     415        return EOK;
     416
     417error:
     418        bithenge_blob_dec_ref(source);
     419        free(blob);
     420        return rc;
     421}
     422
     423/** Create a blob from data offset within another blob. This function takes
     424 * ownership of a reference to @a blob.
     425 * @param[out] out Stores the created blob node. On error, this is unchanged.
     426 * @param[in] source The input blob.
     427 * @param offset The offset within the input blob at which the new blob will start.
     428 * @return EOK on success or an error code from errno.h. */
     429int bithenge_new_offset_blob(bithenge_node_t **out, bithenge_blob_t *source,
     430    aoff64_t offset)
     431{
     432        return new_subblob(out, source, offset, 0, false);
     433}
     434
     435/** Create a blob from part of another blob. This function takes ownership of a
     436 * reference to @a blob.
     437 * @param[out] out Stores the created blob node. On error, this is unchanged.
     438 * @param[in] source The input blob.
     439 * @param offset The offset within the input blob at which the new blob will start.
     440 * @param size The size of the new blob.
     441 * @return EOK on success or an error code from errno.h. */
     442int bithenge_new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
     443    aoff64_t offset, aoff64_t size)
     444{
     445        return new_subblob(out, source, offset, size, true);
     446}
     447
    298448/** Check whether the contents of two blobs are equal.
    299449 * @memberof bithenge_blob_t
Note: See TracChangeset for help on using the changeset viewer.