Changeset 04a7435f in mainline for uspace/app/bithenge/blob.c
- Timestamp:
- 2012-06-26T19:56:26Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 978ccaf1
- Parents:
- f2da0bb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/blob.c
rf2da0bb r04a7435f 296 296 } 297 297 298 typedef 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 306 static inline subblob_t *blob_as_subblob(bithenge_blob_t *base) 307 { 308 return (subblob_t *)base; 309 } 310 311 static inline bithenge_blob_t *subblob_as_blob(subblob_t *blob) 312 { 313 return &blob->base; 314 } 315 316 static 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 329 static 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 342 static 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 350 static const bithenge_random_access_blob_ops_t subblob_ops = { 351 .size = subblob_size, 352 .read = subblob_read, 353 .destroy = subblob_destroy, 354 }; 355 356 static bool is_subblob(bithenge_blob_t *blob) 357 { 358 return blob->base.blob_ops == &subblob_ops; 359 } 360 361 static 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 417 error: 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. */ 429 int 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. */ 442 int 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 298 448 /** Check whether the contents of two blobs are equal. 299 449 * @memberof bithenge_blob_t
Note:
See TracChangeset
for help on using the changeset viewer.