Changeset 0ce0103 in mainline
- Timestamp:
- 2012-08-06T04:15:33Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f9c314a5
- Parents:
- c3437d9
- Location:
- uspace
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/blob.c
rc3437d9 r0ce0103 55 55 assert(ops); 56 56 assert(ops->destroy); 57 assert(ops->read );57 assert(ops->read || ops->read_bits); 58 58 assert(ops->size); 59 59 … … 339 339 } 340 340 341 static int subblob_read_bits(bithenge_blob_t *base, aoff64_t offset, 342 char *buffer, aoff64_t *size, bool little_endian) 343 { 344 subblob_t *blob = blob_as_subblob(base); 345 if (blob->size_matters) { 346 if (offset > blob->size) 347 return EINVAL; 348 *size = min(*size, blob->size - offset); 349 } 350 offset += blob->offset; 351 return bithenge_blob_read_bits(blob->source, offset, buffer, size, 352 little_endian); 353 } 354 341 355 static void subblob_destroy(bithenge_blob_t *base) 342 356 { … … 349 363 .size = subblob_size, 350 364 .read = subblob_read, 365 .read_bits = subblob_read_bits, 351 366 .destroy = subblob_destroy, 352 367 }; -
uspace/app/bithenge/blob.h
rc3437d9 r0ce0103 56 56 int (*read)(bithenge_blob_t *self, aoff64_t offset, char *buffer, 57 57 aoff64_t *size); 58 /** @copydoc bithenge_blob_t::bithenge_blob_read_bits */ 59 int (*read_bits)(bithenge_blob_t *self, aoff64_t offset, char *buffer, 60 aoff64_t *size, bool little_endian); 58 61 /** Destroy the blob. 59 62 * @param blob The blob. */ … … 146 149 assert(self); 147 150 assert(self->base.blob_ops); 151 if (!self->base.blob_ops->read) 152 return EINVAL; 148 153 return self->base.blob_ops->read(self, offset, buffer, size); 154 } 155 156 /** Read part of the bit blob. If the requested data extends beyond the end of 157 * the blob, the data up until the end of the blob will be read. If the offset 158 * is beyond the end of the blob, even if the size is zero, an error will be 159 * returned. 160 * 161 * @memberof bithenge_blob_t 162 * @param self The blob. 163 * @param offset Byte offset within the blob. 164 * @param[out] buffer Buffer to read into. If an error occurs, the contents are 165 * undefined. 166 * @param[in,out] size Number of bytes to read; may be 0. If the requested 167 * range extends beyond the end of the blob, the actual number of bytes read 168 * should be stored here. If an error occurs, the contents are undefined. 169 * @param little_endian If true, bytes will be filled starting at the least 170 * significant bit; otherwise, they will be filled starting at the most 171 * significant bit. 172 * @return EOK on success or an error code from errno.h. 173 */ 174 static inline int bithenge_blob_read_bits(bithenge_blob_t *self, 175 aoff64_t offset, char *buffer, aoff64_t *size, bool little_endian) 176 { 177 assert(self); 178 assert(self->base.blob_ops); 179 if (!self->base.blob_ops->read_bits) 180 return EINVAL; 181 return self->base.blob_ops->read_bits(self, offset, buffer, size, 182 little_endian); 149 183 } 150 184 -
uspace/app/bithenge/transform.c
rc3437d9 r0ce0103 363 363 } 364 364 365 366 367 /***************** ascii *****************/ 368 365 369 static int ascii_apply(bithenge_transform_t *self, bithenge_scope_t *scope, 366 370 bithenge_node_t *in, bithenge_node_t **out) … … 404 408 }; 405 409 410 411 412 /***************** bit *****************/ 413 414 static int bit_prefix_apply(bithenge_transform_t *self, 415 bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node, 416 aoff64_t *out_size) 417 { 418 char buffer; 419 *out_size = 1; 420 int rc = bithenge_blob_read_bits(blob, 0, &buffer, out_size, true); 421 if (rc != EOK) 422 return rc; 423 if (*out_size != 1) 424 return EINVAL; 425 return bithenge_new_boolean_node(out_node, (buffer & 1) != 0); 426 } 427 428 static const bithenge_transform_ops_t bit_ops = { 429 .prefix_apply = bit_prefix_apply, 430 .destroy = transform_indestructible, 431 }; 432 433 /** A transform that decodes a bit as a boolean. */ 434 bithenge_transform_t bithenge_bit_transform = { 435 &bit_ops, 1, 0 436 }; 437 438 439 440 /***************** bits_be, bits_le *****************/ 441 442 typedef struct { 443 bithenge_blob_t base; 444 bithenge_blob_t *bytes; 445 bool little_endian; 446 } bits_xe_blob_t; 447 448 static bits_xe_blob_t *blob_as_bits_xe(bithenge_blob_t *base) 449 { 450 return (bits_xe_blob_t *)base; 451 } 452 453 static bithenge_blob_t *bits_xe_as_blob(bits_xe_blob_t *self) 454 { 455 return &self->base; 456 } 457 458 static int bits_xe_size(bithenge_blob_t *base, aoff64_t *out) 459 { 460 bits_xe_blob_t *self = blob_as_bits_xe(base); 461 int rc = bithenge_blob_size(self->bytes, out); 462 *out *= 8; 463 return rc; 464 } 465 466 static uint8_t reverse_byte(uint8_t val) 467 { 468 val = ((val & 0x0f) << 4) ^ ((val & 0xf0) >> 4); 469 val = ((val & 0x33) << 2) ^ ((val & 0xcc) >> 2); 470 val = ((val & 0x55) << 1) ^ ((val & 0xaa) >> 1); 471 return val; 472 } 473 474 static int bits_xe_read_bits(bithenge_blob_t *base, aoff64_t offset, 475 char *buffer, aoff64_t *size, bool little_endian) 476 { 477 bits_xe_blob_t *self = blob_as_bits_xe(base); 478 aoff64_t bytes_offset = offset / 8; 479 aoff64_t bit_offset = offset % 8; 480 aoff64_t output_num_bytes = (*size + 7) / 8; 481 aoff64_t bytes_size = (*size + bit_offset + 7) / 8; 482 bool separate_buffer = bit_offset != 0; 483 uint8_t *bytes_buffer; 484 if (separate_buffer) { 485 /* Allocate an extra byte, to make sure byte1 can be read. */ 486 bytes_buffer = malloc(bytes_size + 1); 487 if (!bytes_buffer) 488 return ENOMEM; 489 } else 490 bytes_buffer = (uint8_t *)buffer; 491 492 int rc = bithenge_blob_read(self->bytes, bytes_offset, 493 (char *)bytes_buffer, &bytes_size); 494 if (rc != EOK) 495 goto end; 496 *size = min(*size, bytes_size * 8 - bit_offset); 497 498 if (little_endian != self->little_endian) 499 for (aoff64_t i = 0; i < bytes_size; i++) 500 bytes_buffer[i] = reverse_byte(bytes_buffer[i]); 501 502 if (bit_offset || separate_buffer) { 503 for (aoff64_t i = 0; i < output_num_bytes; i++) { 504 uint8_t byte0 = bytes_buffer[i]; 505 uint8_t byte1 = bytes_buffer[i + 1]; 506 buffer[i] = little_endian ? 507 (byte0 >> bit_offset) ^ (byte1 << (8 - bit_offset)) : 508 (byte0 << bit_offset) ^ (byte1 >> (8 - bit_offset)); 509 } 510 } 511 512 end: 513 if (separate_buffer) 514 free(bytes_buffer); 515 return rc; 516 } 517 518 static void bits_xe_destroy(bithenge_blob_t *base) 519 { 520 bits_xe_blob_t *self = blob_as_bits_xe(base); 521 bithenge_blob_dec_ref(self->bytes); 522 free(self); 523 } 524 525 static const bithenge_random_access_blob_ops_t bits_xe_blob_ops = { 526 .size = bits_xe_size, 527 .read_bits = bits_xe_read_bits, 528 .destroy = bits_xe_destroy, 529 }; 530 531 static int bits_xe_apply(bithenge_transform_t *self, bithenge_scope_t *scope, 532 bithenge_node_t *in, bithenge_node_t **out) 533 { 534 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB) 535 return EINVAL; 536 bits_xe_blob_t *blob = malloc(sizeof(*blob)); 537 if (!blob) 538 return ENOMEM; 539 int rc = bithenge_init_random_access_blob(bits_xe_as_blob(blob), 540 &bits_xe_blob_ops); 541 if (rc != EOK) { 542 free(blob); 543 return rc; 544 } 545 bithenge_node_inc_ref(in); 546 blob->bytes = bithenge_node_as_blob(in); 547 blob->little_endian = (self == &bithenge_bits_le_transform); 548 *out = bithenge_blob_as_node(bits_xe_as_blob(blob)); 549 return EOK; 550 } 551 552 static const bithenge_transform_ops_t bits_xe_ops = { 553 .apply = bits_xe_apply, 554 .destroy = transform_indestructible, 555 }; 556 557 /** A transform that converts a byte blob to a bit blob, most-significant bit 558 * first. */ 559 bithenge_transform_t bithenge_bits_be_transform = { 560 &bits_xe_ops, 1, 0 561 }; 562 563 /** A transform that converts a byte blob to a bit blob, least-significant bit 564 * first. */ 565 bithenge_transform_t bithenge_bits_le_transform = { 566 &bits_xe_ops, 1, 0 567 }; 568 569 570 571 /***************** invalid *****************/ 572 406 573 static int invalid_apply(bithenge_transform_t *self, bithenge_scope_t *scope, 407 574 bithenge_node_t *in, bithenge_node_t **out) … … 419 586 &invalid_ops, 1, 0 420 587 }; 588 589 590 591 /***************** known_length *****************/ 421 592 422 593 static int known_length_apply(bithenge_transform_t *self, … … 564 735 MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint32_t_be2host, prefix_length_8); 565 736 737 738 739 /***************** uint_be, uint_le *****************/ 740 741 static int uint_xe_prefix_apply(bithenge_transform_t *self, 742 bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node, 743 aoff64_t *out_size) 744 { 745 bool little_endian = (self == &bithenge_uint_le_transform); 746 bithenge_node_t *num_bits_node; 747 int rc = bithenge_scope_get_param(scope, 0, &num_bits_node); 748 if (rc != EOK) 749 return rc; 750 if (bithenge_node_type(num_bits_node) != BITHENGE_NODE_INTEGER) { 751 bithenge_node_dec_ref(num_bits_node); 752 return EINVAL; 753 } 754 bithenge_int_t num_bits = bithenge_integer_node_value(num_bits_node); 755 bithenge_node_dec_ref(num_bits_node); 756 if (num_bits < 0) 757 return EINVAL; 758 if ((size_t)num_bits > sizeof(bithenge_int_t) * 8 - 1) 759 return EINVAL; 760 761 *out_size = num_bits; 762 uint8_t buffer[sizeof(bithenge_int_t)]; 763 rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, out_size, 764 little_endian); 765 if (rc != EOK) 766 return rc; 767 if (*out_size != (aoff64_t)num_bits) 768 return EINVAL; 769 770 bithenge_int_t result = 0; 771 bithenge_int_t num_easy_bytes = num_bits / 8; 772 if (little_endian) { 773 for (bithenge_int_t i = 0; i < num_easy_bytes; i++) 774 result += buffer[i] << 8 * i; 775 if (num_bits % 8) 776 result += (buffer[num_easy_bytes] & 777 ((1 << num_bits % 8) - 1)) << 8 * num_easy_bytes; 778 } else { 779 for (bithenge_int_t i = 0; i < num_easy_bytes; i++) 780 result += buffer[i] << (num_bits - 8 * (i + 1)); 781 if (num_bits % 8) 782 result += buffer[num_easy_bytes] >> (8 - num_bits % 8); 783 } 784 785 return bithenge_new_integer_node(out_node, result); 786 } 787 788 static const bithenge_transform_ops_t uint_xe_ops = { 789 .prefix_apply = uint_xe_prefix_apply, 790 .destroy = transform_indestructible, 791 }; 792 793 /** A transform that reads an unsigned integer from an arbitrary number of 794 * bits, most-significant bit first. */ 795 bithenge_transform_t bithenge_uint_be_transform = { 796 &uint_xe_ops, 1, 1 797 }; 798 799 /** A transform that reads an unsigned integer from an arbitrary number of 800 * bits, least-significant bit first. */ 801 bithenge_transform_t bithenge_uint_le_transform = { 802 &uint_xe_ops, 1, 1 803 }; 804 805 806 807 /***************** zero_terminated *****************/ 808 566 809 static int zero_terminated_apply(bithenge_transform_t *self, 567 810 bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out) … … 621 864 static bithenge_named_transform_t primitive_transforms[] = { 622 865 {"ascii", &bithenge_ascii_transform}, 866 {"bit", &bithenge_bit_transform}, 867 {"bits_be", &bithenge_bits_be_transform}, 868 {"bits_le", &bithenge_bits_le_transform}, 623 869 {"known_length", &bithenge_known_length_transform}, 624 870 {"nonzero_boolean", &bithenge_nonzero_boolean_transform}, 625 871 {"uint8", &bithenge_uint8_transform}, 872 {"uint16be", &bithenge_uint16be_transform}, 626 873 {"uint16le", &bithenge_uint16le_transform}, 627 {"uint 16be", &bithenge_uint16be_transform},874 {"uint32be", &bithenge_uint32be_transform}, 628 875 {"uint32le", &bithenge_uint32le_transform}, 629 {"uint 32be", &bithenge_uint32be_transform},876 {"uint64be", &bithenge_uint64be_transform}, 630 877 {"uint64le", &bithenge_uint64le_transform}, 631 {"uint64be", &bithenge_uint64be_transform}, 878 {"uint_be", &bithenge_uint_be_transform}, 879 {"uint_le", &bithenge_uint_le_transform}, 632 880 {"zero_terminated", &bithenge_zero_terminated_transform}, 633 881 {NULL, NULL} -
uspace/app/bithenge/transform.h
rc3437d9 r0ce0103 112 112 113 113 extern bithenge_transform_t bithenge_ascii_transform; 114 extern bithenge_transform_t bithenge_bit_transform; 115 extern bithenge_transform_t bithenge_bits_be_transform; 116 extern bithenge_transform_t bithenge_bits_le_transform; 114 117 extern bithenge_transform_t bithenge_invalid_transform; 115 118 extern bithenge_transform_t bithenge_known_length_transform; … … 122 125 extern bithenge_transform_t bithenge_uint64le_transform; 123 126 extern bithenge_transform_t bithenge_uint64be_transform; 127 extern bithenge_transform_t bithenge_uint_le_transform; 128 extern bithenge_transform_t bithenge_uint_be_transform; 124 129 extern bithenge_transform_t bithenge_zero_terminated_transform; 125 130 extern bithenge_named_transform_t *bithenge_primitive_transforms;
Note:
See TracChangeset
for help on using the changeset viewer.