Changeset 600f5d1 in mainline for uspace/app/bithenge/transform.c
- Timestamp:
- 2012-06-27T20:10:30Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 02dcb20
- Parents:
- 978ccaf1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/transform.c
r978ccaf1 r600f5d1 61 61 } 62 62 63 static int ascii_apply(bithenge_transform_t *self, 64 bithenge_node_t *in, bithenge_node_t **out) 65 { 66 int rc; 67 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB) 68 return EINVAL; 69 bithenge_blob_t *blob = bithenge_node_as_blob(in); 70 aoff64_t size; 71 rc = bithenge_blob_size(blob, &size); 72 if (rc != EOK) 73 return rc; 74 75 char *buffer = malloc(size + 1); 76 if (!buffer) 77 return ENOMEM; 78 aoff64_t size_read = size; 79 rc = bithenge_blob_read(blob, 0, buffer, &size_read); 80 if (rc != EOK) { 81 free(buffer); 82 return rc; 83 } 84 if (size_read != size) { 85 free(buffer); 86 return EINVAL; 87 } 88 buffer[size] = '\0'; 89 90 /* TODO: what if the OS encoding is incompatible with ASCII? */ 91 return bithenge_new_string_node(out, buffer, true); 92 } 93 94 static const bithenge_transform_ops_t ascii_ops = { 95 .apply = ascii_apply, 96 .destroy = transform_indestructible, 97 }; 98 99 /** The ASCII text transform. */ 100 bithenge_transform_t bithenge_ascii_transform = { 101 &ascii_ops, 1 102 }; 103 63 104 static int uint32le_apply(bithenge_transform_t *self, bithenge_node_t *in, 64 105 bithenge_node_t **out) … … 130 171 }; 131 172 173 static int zero_terminated_apply(bithenge_transform_t *self, 174 bithenge_node_t *in, bithenge_node_t **out) 175 { 176 int rc; 177 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB) 178 return EINVAL; 179 bithenge_blob_t *blob = bithenge_node_as_blob(in); 180 aoff64_t size; 181 rc = bithenge_blob_size(blob, &size); 182 if (rc != EOK) 183 return rc; 184 if (size < 1) 185 return EINVAL; 186 char ch; 187 aoff64_t size_read = 1; 188 rc = bithenge_blob_read(blob, size - 1, &ch, &size_read); 189 if (rc != EOK) 190 return rc; 191 if (size_read != 1 || ch != '\0') 192 return EINVAL; 193 bithenge_blob_inc_ref(blob); 194 return bithenge_new_subblob(out, blob, 0, size - 1); 195 } 196 197 static int zero_terminated_prefix_length(bithenge_transform_t *self, 198 bithenge_blob_t *blob, aoff64_t *out) 199 { 200 int rc; 201 char buffer[4096]; 202 aoff64_t offset = 0, size_read = sizeof(buffer); 203 do { 204 rc = bithenge_blob_read(blob, offset, buffer, &size_read); 205 if (rc != EOK) 206 return rc; 207 char *found = memchr(buffer, '\0', size_read); 208 if (found) { 209 *out = found - buffer + offset + 1; 210 return EOK; 211 } 212 offset += size_read; 213 } while (size_read == sizeof(buffer)); 214 return EINVAL; 215 } 216 217 static const bithenge_transform_ops_t zero_terminated_ops = { 218 .apply = zero_terminated_apply, 219 .prefix_length = zero_terminated_prefix_length, 220 .destroy = transform_indestructible, 221 }; 222 223 /** The zero-terminated data transform. */ 224 bithenge_transform_t bithenge_zero_terminated_transform = { 225 &zero_terminated_ops, 1 226 }; 227 132 228 static bithenge_named_transform_t primitive_transforms[] = { 229 {"ascii", &bithenge_ascii_transform}, 133 230 {"uint32le", &bithenge_uint32le_transform}, 134 231 {"uint32be", &bithenge_uint32be_transform}, 232 {"zero_terminated", &bithenge_zero_terminated_transform}, 135 233 {NULL, NULL} 136 234 }; … … 367 465 { 368 466 int rc; 369 struct_transform_t *self = 370 malloc(sizeof(*self)); 467 struct_transform_t *self = malloc(sizeof(*self)); 371 468 if (!self) { 372 469 rc = ENOMEM; … … 386 483 } 387 484 485 typedef struct { 486 bithenge_transform_t base; 487 bithenge_transform_t **xforms; 488 size_t num; 489 } compose_transform_t; 490 491 static bithenge_transform_t *compose_as_transform(compose_transform_t *xform) 492 { 493 return &xform->base; 494 } 495 496 static compose_transform_t *transform_as_compose(bithenge_transform_t *xform) 497 { 498 return (compose_transform_t *)xform; 499 } 500 501 static int compose_apply(bithenge_transform_t *base, bithenge_node_t *in, 502 bithenge_node_t **out) 503 { 504 int rc; 505 compose_transform_t *self = transform_as_compose(base); 506 bithenge_node_inc_ref(in); 507 508 /* i ranges from (self->num - 1) to 0 inside the loop. */ 509 for (size_t i = self->num; i--; ) { 510 bithenge_node_t *tmp; 511 rc = bithenge_transform_apply(self->xforms[i], in, &tmp); 512 bithenge_node_dec_ref(in); 513 if (rc != EOK) 514 return rc; 515 in = tmp; 516 } 517 518 *out = in; 519 return rc; 520 } 521 522 static int compose_prefix_length(bithenge_transform_t *base, 523 bithenge_blob_t *blob, aoff64_t *out) 524 { 525 compose_transform_t *self = transform_as_compose(base); 526 return bithenge_transform_prefix_length(self->xforms[self->num - 1], 527 blob, out); 528 } 529 530 static void compose_destroy(bithenge_transform_t *base) 531 { 532 compose_transform_t *self = transform_as_compose(base); 533 for (size_t i = 0; i < self->num; i++) 534 bithenge_transform_dec_ref(self->xforms[i]); 535 free(self->xforms); 536 free(self); 537 } 538 539 static const bithenge_transform_ops_t compose_transform_ops = { 540 .apply = compose_apply, 541 .prefix_length = compose_prefix_length, 542 .destroy = compose_destroy, 543 }; 544 545 /** Create a composition of multiple transforms. When the result is applied to a 546 * node, each transform is applied in turn, with the last transform applied 547 * first. @a xforms may contain any number of transforms or no transforms at 548 * all. This function takes ownership of @a xforms and the references therein. 549 * @param[out] out Holds the result. 550 * @param[in] xforms The transforms to apply. 551 * @param num The number of transforms. 552 * @return EOK on success or an error code from errno.h. */ 553 int bithenge_new_composed_transform(bithenge_transform_t **out, 554 bithenge_transform_t **xforms, size_t num) 555 { 556 if (num == 0) { 557 /* TODO: optimize */ 558 } else if (num == 1) { 559 *out = xforms[0]; 560 free(xforms); 561 return EOK; 562 } 563 564 int rc; 565 compose_transform_t *self = malloc(sizeof(*self)); 566 if (!self) { 567 rc = ENOMEM; 568 goto error; 569 } 570 rc = bithenge_init_transform(compose_as_transform(self), 571 &compose_transform_ops); 572 if (rc != EOK) 573 goto error; 574 self->xforms = xforms; 575 self->num = num; 576 *out = compose_as_transform(self); 577 return EOK; 578 error: 579 for (size_t i = 0; i < num; i++) 580 bithenge_transform_dec_ref(xforms[i]); 581 free(xforms); 582 free(self); 583 return rc; 584 } 585 388 586 /** @} 389 587 */
Note:
See TracChangeset
for help on using the changeset viewer.