Changeset 600f5d1 in mainline
- Timestamp:
- 2012-06-27T20:10:30Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 02dcb20
- Parents:
- 978ccaf1
- Location:
- uspace/app/bithenge
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/helenos/os.h
r978ccaf1 r600f5d1 35 35 #include <macros.h> 36 36 #include <mem.h> 37 #include <stdlib.h> 37 38 #include <str.h> 38 39 #include <str_error.h> … … 67 68 } 68 69 70 static inline void *memchr(const void *s, int c, size_t n) 71 { 72 for (size_t i = 0; i < n; i++) 73 if (((char *)s)[i] == c) 74 return (void *)(s + i); 75 return NULL; 76 } 77 69 78 #endif -
uspace/app/bithenge/script.c
r978ccaf1 r600f5d1 177 177 return; 178 178 } else if (isalpha(ch)) { 179 while (isalnum(state->buffer[state->buffer_pos])) 179 while (isalnum(state->buffer[state->buffer_pos]) 180 || state->buffer[state->buffer_pos] == '_') 180 181 state->buffer_pos++; 181 182 char *value = str_ndup(state->buffer + state->old_buffer_pos, … … 308 309 expect(state, '{'); 309 310 while (state->error == EOK && state->token != '}') { 310 expect(state, '.'); 311 subxforms[num].name = expect_identifier(state); 312 expect(state, TOKEN_LEFT_ARROW); 311 if (state->token == '.') { 312 expect(state, '.'); 313 subxforms[num].name = expect_identifier(state); 314 expect(state, TOKEN_LEFT_ARROW); 315 } else { 316 subxforms[num].name = NULL; 317 expect(state, TOKEN_LEFT_ARROW); 318 } 313 319 subxforms[num].transform = parse_transform(state); 314 320 expect(state, ';'); … … 339 345 } 340 346 341 /** Parse a transform .347 /** Parse a transform without composition. 342 348 * @return The parsed transform, or NULL if an error occurred. */ 343 static bithenge_transform_t *parse_transform (state_t *state)349 static bithenge_transform_t *parse_transform_no_compose(state_t *state) 344 350 { 345 351 if (state->token == TOKEN_IDENTIFIER) { … … 356 362 return NULL; 357 363 } 364 } 365 366 /** Parse a transform. 367 * @return The parsed transform, or NULL if an error occurred. */ 368 static bithenge_transform_t *parse_transform(state_t *state) 369 { 370 bithenge_transform_t *result = parse_transform_no_compose(state); 371 bithenge_transform_t **xforms = NULL; 372 size_t num = 1; 373 while (state->token == TOKEN_LEFT_ARROW) { 374 expect(state, TOKEN_LEFT_ARROW); 375 xforms = state_realloc(state, xforms, 376 (num + 1) * sizeof(*xforms)); 377 if (state->error != EOK) 378 break; 379 xforms[num] = parse_transform_no_compose(state); 380 num++; 381 } 382 if (state->error != EOK) { 383 while (xforms && num--) 384 bithenge_transform_dec_ref(xforms[num]); 385 free(xforms); 386 bithenge_transform_dec_ref(result); 387 return NULL; 388 } 389 if (xforms) { 390 xforms[0] = result; 391 int rc = bithenge_new_composed_transform(&result, xforms, num); 392 if (rc != EOK) { 393 error_errno(state, rc); 394 return NULL; 395 } 396 } 397 return result; 358 398 } 359 399 -
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 */ -
uspace/app/bithenge/transform.h
r978ccaf1 r600f5d1 118 118 } bithenge_named_transform_t; 119 119 120 extern bithenge_transform_t bithenge_ascii_transform; 120 121 extern bithenge_transform_t bithenge_uint32le_transform; 121 122 extern bithenge_transform_t bithenge_uint32be_transform; 123 extern bithenge_transform_t bithenge_zero_terminated_transform; 122 124 extern bithenge_named_transform_t *bithenge_primitive_transforms; 123 125 124 126 int bithenge_init_transform(bithenge_transform_t *self, 125 127 const bithenge_transform_ops_t *ops); 126 127 128 int bithenge_new_struct(bithenge_transform_t **out, 128 129 bithenge_named_transform_t *subtransforms); 130 int bithenge_new_composed_transform(bithenge_transform_t **, 131 bithenge_transform_t **, size_t); 129 132 130 133 #endif -
uspace/app/bithenge/tree.c
r978ccaf1 r600f5d1 226 226 assert(out); 227 227 bithenge_node_t *self = malloc(sizeof(*self)); 228 if (!self) 228 if (!self) { 229 if (needs_free) 230 free((void *)value); 229 231 return ENOMEM; 232 } 230 233 self->type = BITHENGE_NODE_STRING; 231 234 self->refs = 1;
Note:
See TracChangeset
for help on using the changeset viewer.