Mercurial > hg > dmlib
comparison src/dmres.c @ 2437:f7d54ac51880
Fix and improvements to dmres MemIO subsystem.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 25 Feb 2020 07:26:40 +0200 |
parents | 69a5af2eb1ea |
children | fd31b5d1ed5e |
comparison
equal
deleted
inserted
replaced
2436:b7f622d39efc | 2437:f7d54ac51880 |
---|---|
47 if (node == NULL) | 47 if (node == NULL) |
48 return NULL; | 48 return NULL; |
49 | 49 |
50 node->lib = lib; | 50 node->lib = lib; |
51 node->filename = dm_strdup(filename); | 51 node->filename = dm_strdup(filename); |
52 node->rawSize = size; | 52 node->memAlloc = node->memSize = size; |
53 node->flags = flags; | 53 node->flags = flags; |
54 | 54 |
55 return node; | 55 return node; |
56 } | 56 } |
57 | 57 |
73 | 73 |
74 void dmResourceFreeRawData(DMResource *node) | 74 void dmResourceFreeRawData(DMResource *node) |
75 { | 75 { |
76 if ((node->flags & DMF_UNALLOCATED) == 0) | 76 if ((node->flags & DMF_UNALLOCATED) == 0) |
77 { | 77 { |
78 dmFree(node->rawData); | 78 dmFree(node->memData); |
79 node->rawData = NULL; | 79 node->memData = NULL; |
80 node->flags &= ~DMF_LOADED_RAW; | 80 node->flags &= ~DMF_LOADED_RAW; |
81 } | 81 } |
82 } | 82 } |
83 | 83 |
84 | 84 |
229 static off_t dm_stdio_fsize(DMResource *fh) | 229 static off_t dm_stdio_fsize(DMResource *fh) |
230 { | 230 { |
231 off_t savePos, fileSize; | 231 off_t savePos, fileSize; |
232 | 232 |
233 // Check if the size is cached | 233 // Check if the size is cached |
234 if (fh->rawSize != 0) | 234 if (fh->memSize != 0) |
235 return fh->rawSize; | 235 return fh->memSize; |
236 | 236 |
237 // Get file size | 237 // Get file size |
238 if ((savePos = dm_stdio_ftell(fh)) < 0) | 238 if ((savePos = dm_stdio_ftell(fh)) < 0) |
239 return -1; | 239 return -1; |
240 | 240 |
245 return -1; | 245 return -1; |
246 | 246 |
247 if (dm_stdio_fseek(fh, savePos, SEEK_SET) != 0) | 247 if (dm_stdio_fseek(fh, savePos, SEEK_SET) != 0) |
248 return -1; | 248 return -1; |
249 | 249 |
250 fh->rawSize = fileSize; | 250 fh->memSize = fileSize; |
251 return fileSize; | 251 return fileSize; |
252 } | 252 } |
253 | 253 |
254 | 254 |
255 static BOOL dm_stdio_feof(DMResource *fh) | 255 static BOOL dm_stdio_feof(DMResource *fh) |
296 if (ret != DMERR_OK) | 296 if (ret != DMERR_OK) |
297 return ret; | 297 return ret; |
298 | 298 |
299 dm_stdio_fsize(handle); | 299 dm_stdio_fsize(handle); |
300 | 300 |
301 handle->rawData = dmMalloc(handle->rawSize); | 301 handle->memData = dmMalloc(handle->memSize); |
302 if (handle->rawData == NULL) | 302 if (handle->memData == NULL) |
303 return DMERR_MALLOC; | 303 return DMERR_MALLOC; |
304 | 304 |
305 if (dm_stdio_fread(handle->rawData, sizeof(Uint8), handle->rawSize, handle) != handle->rawSize) | 305 handle->memAlloc = handle->memSize; |
306 | |
307 if (dm_stdio_fread(handle->memData, sizeof(Uint8), handle->memSize, handle) != handle->memSize) | |
306 return DMERR_FREAD; | 308 return DMERR_FREAD; |
307 | 309 |
308 return DMERR_OK; | 310 return DMERR_OK; |
309 } | 311 } |
310 | 312 |
381 goto out; | 383 goto out; |
382 } | 384 } |
383 | 385 |
384 // Initialize decompression | 386 // Initialize decompression |
385 memset(&zstr, 0, sizeof(zstr)); | 387 memset(&zstr, 0, sizeof(zstr)); |
386 zstr.next_out = handle->rawData; | 388 zstr.next_out = handle->memData; |
387 zstr.avail_out = handle->rawSize; | 389 zstr.avail_out = handle->memSize; |
388 cdataLeft = node->length; | 390 cdataLeft = node->length; |
389 | 391 |
390 if ((zret = inflateInit(&zstr)) != Z_OK) | 392 if ((zret = inflateInit(&zstr)) != Z_OK) |
391 { | 393 { |
392 ret = dmErrorDBG(DMERR_INIT_FAIL, | 394 ret = dmErrorDBG(DMERR_INIT_FAIL, |
444 if ((ret = dmZLibInitInflate(&ctx)) != DMERR_OK) | 446 if ((ret = dmZLibInitInflate(&ctx)) != DMERR_OK) |
445 goto out; | 447 goto out; |
446 | 448 |
447 ctx.inBuffer = ctx.inBufferStart = inBuf; | 449 ctx.inBuffer = ctx.inBufferStart = inBuf; |
448 ctx.inBufferEnd = inBuf + node->length; | 450 ctx.inBufferEnd = inBuf + node->length; |
449 ctx.outBuffer = ctx.outBufferStart = handle->rawData; | 451 ctx.outBuffer = ctx.outBufferStart = handle->memData; |
450 ctx.outBufferEnd = handle->rawData + node->size; | 452 ctx.outBufferEnd = handle->memData + node->size; |
451 ctx.expandable = FALSE; | 453 ctx.expandable = FALSE; |
452 | 454 |
453 // Attempt decompression | 455 // Attempt decompression |
454 if ((ret = dmZLibParseHeader(&ctx, TRUE)) != DMERR_OK) | 456 if ((ret = dmZLibParseHeader(&ctx, TRUE)) != DMERR_OK) |
455 goto out; | 457 goto out; |
456 | 458 |
457 if ((ret = dmZLibInflate(&ctx)) != DMERR_OK) | 459 if ((ret = dmZLibInflate(&ctx)) != DMERR_OK) |
458 goto out; | 460 goto out; |
459 | 461 |
460 handle->rawData = ctx.outBufferStart; | 462 handle->memData = ctx.outBufferStart; |
461 handle->rawSize = ctx.outBuffer - ctx.outBufferStart; | 463 handle->memSize = ctx.outBuffer - ctx.outBufferStart; |
462 | 464 |
463 out: | 465 out: |
464 dmZLibCloseInflate(&ctx); | 466 dmZLibCloseInflate(&ctx); |
465 dmFree(inBuf); | 467 dmFree(inBuf); |
466 return ret; | 468 return ret; |
493 "Could not seek node position in PACK file.\n"); | 495 "Could not seek node position in PACK file.\n"); |
494 goto out; | 496 goto out; |
495 } | 497 } |
496 | 498 |
497 // Allocate memory for the node | 499 // Allocate memory for the node |
498 if ((handle->rawData = dmMalloc(node->size)) == NULL) | 500 if ((handle->memData = dmMalloc(node->size)) == NULL) |
499 { | 501 { |
500 ret = dmErrorDBG(DMERR_MALLOC, | 502 ret = dmErrorDBG(DMERR_MALLOC, |
501 "Failed to allocate node data for '%s' (%d bytes).\n", | 503 "Failed to allocate node data for '%s' (%d bytes).\n", |
502 handle->filename, node->size); | 504 handle->filename, node->size); |
503 goto out; | 505 goto out; |
507 if (handle->flags & DMF_COMPRESSED) | 509 if (handle->flags & DMF_COMPRESSED) |
508 { | 510 { |
509 if ((ret = dm_pack_decompress(handle, node)) != DMERR_OK) | 511 if ((ret = dm_pack_decompress(handle, node)) != DMERR_OK) |
510 goto out; | 512 goto out; |
511 | 513 |
512 if (handle->rawSize != node->size) | 514 if (handle->memSize != node->size) |
513 { | 515 { |
514 ret = dmErrorDBG(DMERR_COMPRESSION, | 516 ret = dmErrorDBG(DMERR_COMPRESSION, |
515 "Decompressed data size for '%s' does not match size " | 517 "Decompressed data size for '%s' does not match size " |
516 "stored in PACK entry (%" DM_PRIu_SIZE_T " <> %d).\n", | 518 "stored in PACK entry (%" DM_PRIu_SIZE_T " <> %d).\n", |
517 handle->filename, handle->rawSize, node->size); | 519 handle->filename, handle->memSize, node->size); |
518 } | 520 } |
519 } | 521 } |
520 else | 522 else |
521 { | 523 { |
522 if (node->size != node->length) | 524 if (node->size != node->length) |
524 ret = dmErrorDBG(DMERR_INVALID_DATA, | 526 ret = dmErrorDBG(DMERR_INVALID_DATA, |
525 "Node '%s' raw size and length fields differ for uncompressed node: %d <> %d.\n", | 527 "Node '%s' raw size and length fields differ for uncompressed node: %d <> %d.\n", |
526 handle->filename, node->size, node->length); | 528 handle->filename, node->size, node->length); |
527 goto out; | 529 goto out; |
528 } | 530 } |
529 if (fread(handle->rawData, sizeof(Uint8), node->size, handle->lib->packFile->file) != node->size) | 531 if (fread(handle->memData, sizeof(Uint8), node->size, handle->lib->packFile->file) != node->size) |
530 { | 532 { |
531 ret = dmErrorDBG(DMERR_FREAD, | 533 ret = dmErrorDBG(DMERR_FREAD, |
532 "Error reading raw node data '%s', %d bytes.\n", | 534 "Error reading raw node data '%s', %d bytes.\n", |
533 handle->filename, node->size); | 535 handle->filename, node->size); |
534 goto out; | 536 goto out; |
561 dmResourceFreeRawData(fh); | 563 dmResourceFreeRawData(fh); |
562 } | 564 } |
563 #endif | 565 #endif |
564 | 566 |
565 | 567 |
566 static int dm_mem_freset(DMResource *fh) | 568 static BOOL dm_mem_realloc(DMResource *ctx, const size_t newSize) |
567 { | 569 { |
568 fh->rawOffset = 0; | 570 size_t grow; |
571 | |
572 if (ctx->maxSize > 0 && newSize > ctx->maxSize) | |
573 { | |
574 ctx->error = DMERR_BOUNDS; | |
575 return FALSE; | |
576 } | |
577 | |
578 if (newSize < ctx->memAlloc) | |
579 return TRUE; | |
580 | |
581 grow = (ctx->minAlloc > 0) ? ctx->minAlloc : 8 * 1024; | |
582 if (newSize - ctx->memAlloc > grow) | |
583 grow += newSize - ctx->memAlloc; | |
584 | |
585 if (ctx->maxSize > 0 && ctx->memAlloc + grow >= ctx->maxSize) | |
586 { | |
587 ctx->error = DMERR_BOUNDS; | |
588 return FALSE; | |
589 } | |
590 | |
591 ctx->memAlloc += grow; | |
592 if ((ctx->memData = dmRealloc(ctx->memData, ctx->memAlloc)) == NULL) | |
593 { | |
594 ctx->error = DMERR_MALLOC; | |
595 return FALSE; | |
596 } | |
597 | |
598 ctx->memSize = newSize; | |
599 | |
600 return TRUE; | |
601 } | |
602 | |
603 | |
604 static int dm_mem_freset(DMResource *ctx) | |
605 { | |
606 ctx->memOffset = 0; | |
569 return DMERR_OK; | 607 return DMERR_OK; |
570 } | 608 } |
571 | 609 |
572 | 610 |
573 static int dm_mem_ferror(DMResource *fh) | 611 static int dm_mem_ferror(DMResource *ctx) |
574 { | 612 { |
575 return fh->error; | 613 return ctx->error; |
576 } | 614 } |
577 | 615 |
578 | 616 |
579 static int dm_mem_fseek(DMResource *fh, const off_t offset, const int whence) | 617 static int dm_mem_fseek(DMResource *ctx, const off_t offset, const int whence) |
580 { | 618 { |
581 off_t newPos; | 619 off_t newPos; |
582 | 620 |
583 // Calculate the new position | 621 // Calculate the new position |
584 switch (whence) | 622 switch (whence) |
586 case SEEK_SET: | 624 case SEEK_SET: |
587 newPos = offset; | 625 newPos = offset; |
588 break; | 626 break; |
589 | 627 |
590 case SEEK_CUR: | 628 case SEEK_CUR: |
591 newPos = fh->rawOffset + offset; | 629 newPos = ctx->memOffset + offset; |
592 break; | 630 break; |
593 | 631 |
594 case SEEK_END: | 632 case SEEK_END: |
595 newPos = fh->rawSize + offset; | 633 newPos = ctx->memSize + offset; |
596 break; | 634 break; |
597 | 635 |
598 default: | 636 default: |
599 return -1; | 637 return -1; |
600 } | 638 } |
601 | 639 |
602 // Set the new position | 640 // Set the new position |
603 fh->rawOffset = newPos; | 641 ctx->memOffset = newPos; |
604 | 642 |
605 // Check the new position | 643 // Check the new position |
606 if (newPos < 0 && (size_t) newPos >= fh->rawSize) | 644 if (newPos < 0) |
607 return -1; | 645 return -1; |
608 | 646 |
647 //if (!dm_mem_realloc(ctx, newPos)) | |
648 // return -1; | |
649 | |
609 return 0; | 650 return 0; |
610 } | 651 } |
611 | 652 |
612 | 653 |
613 static off_t dm_mem_fsize(DMResource *fh) | 654 static off_t dm_mem_fsize(DMResource *ctx) |
614 { | 655 { |
615 return fh->rawSize; | 656 return ctx->memSize; |
616 } | 657 } |
617 | 658 |
618 | 659 |
619 static off_t dm_mem_ftell(DMResource *fh) | 660 static off_t dm_mem_ftell(DMResource *ctx) |
620 { | 661 { |
621 return fh->rawOffset; | 662 return ctx->memOffset; |
622 } | 663 } |
623 | 664 |
624 | 665 |
625 static BOOL dm_mem_feof(DMResource *fh) | 666 static BOOL dm_mem_feof(DMResource *ctx) |
667 { | |
668 return ((size_t) ctx->memOffset) >= ctx->memSize; | |
669 } | |
670 | |
671 | |
672 static int dm_mem_fgetc(DMResource *ctx) | |
626 { | 673 { |
627 // Check for EOF | 674 // Check for EOF |
628 if ((size_t) fh->rawOffset <= fh->rawSize) | 675 if ((size_t) ctx->memOffset < ctx->memSize) |
629 return FALSE; | 676 return ctx->memData[ctx->memOffset++]; |
630 else | |
631 return TRUE; | |
632 } | |
633 | |
634 | |
635 static int dm_mem_fgetc(DMResource *fh) | |
636 { | |
637 // Check for EOF | |
638 if ((size_t) fh->rawOffset < fh->rawSize) | |
639 return fh->rawData[fh->rawOffset++]; | |
640 else | 677 else |
641 return EOF; | 678 return EOF; |
642 } | 679 } |
643 | 680 |
644 | 681 |
645 static size_t dm_mem_fread(void *buf, size_t size, size_t nmemb, DMResource *fh) | 682 static size_t dm_mem_fread(void *buf, size_t size, size_t nmemb, DMResource *ctx) |
646 { | 683 { |
647 size_t length = (size * nmemb); | 684 size_t length = size * nmemb; |
648 | 685 |
649 // Check if we can read the whole chunk | 686 // Check if we can read the whole chunk |
650 if (((size_t) fh->rawOffset + length) >= fh->rawSize) | 687 if (((size_t) ctx->memOffset + length) >= ctx->memSize) |
651 { | 688 { |
652 nmemb = (fh->rawSize - fh->rawOffset) / size; | 689 nmemb = (ctx->memSize - ctx->memOffset) / size; |
653 length = size * nmemb; | 690 length = size * nmemb; |
654 } | 691 } |
655 | 692 |
656 memcpy(buf, fh->rawData + fh->rawOffset, length); | 693 memcpy(buf, ctx->memData + ctx->memOffset, length); |
657 fh->rawOffset += length; | 694 ctx->memOffset += length; |
658 return nmemb; | 695 return nmemb; |
659 } | 696 } |
660 | 697 |
661 | 698 |
662 static int dm_mem_fputc(int ch, DMResource *fh) | 699 static int dm_mem_fputc(int ch, DMResource *ctx) |
663 { | 700 { |
664 // Check for EOF | 701 // Check for EOF |
665 if ((size_t) fh->rawOffset < fh->rawSize) | 702 if (!dm_mem_realloc(ctx, ctx->memOffset + 1)) |
666 { | |
667 fh->rawData[fh->rawOffset++] = ch; | |
668 return ch; | |
669 } | |
670 else | |
671 return EOF; | 703 return EOF; |
672 } | 704 |
673 | 705 ctx->memData[ctx->memOffset++] = ch; |
674 | 706 return ch; |
675 static size_t dm_mem_fwrite(const void *buf, size_t size, size_t nmemb, DMResource *fh) | 707 } |
676 { | 708 |
677 size_t length = (size * nmemb); | 709 |
710 static size_t dm_mem_fwrite(const void *buf, size_t size, size_t nmemb, DMResource *ctx) | |
711 { | |
712 size_t length = size * nmemb; | |
678 | 713 |
679 // Check if we can write the whole chunk | 714 // Check if we can write the whole chunk |
680 if (((size_t) fh->rawOffset + length) >= fh->rawSize) | 715 if (!dm_mem_realloc(ctx, ctx->memOffset + length)) |
681 { | 716 { |
682 nmemb = (fh->rawSize - fh->rawOffset) / size; | 717 nmemb = (ctx->memSize - ctx->memOffset) / size; |
683 length = size * nmemb; | 718 length = size * nmemb; |
684 } | 719 } |
685 | 720 |
686 if (length > 0) | 721 if (length > 0) |
687 { | 722 { |
688 memcpy(fh->rawData + fh->rawOffset, buf, length); | 723 memcpy(ctx->memData + ctx->memOffset, buf, length); |
689 fh->rawOffset += length; | 724 ctx->memOffset += length; |
690 } | 725 } |
691 return nmemb; | 726 return nmemb; |
692 } | 727 } |
693 | 728 |
694 | 729 |
847 if ((*phandle = handle = dmResourceNew( | 882 if ((*phandle = handle = dmResourceNew( |
848 lib, filename, size, DMF_LOADED_RAW | DMF_UNALLOCATED)) == NULL) | 883 lib, filename, size, DMF_LOADED_RAW | DMF_UNALLOCATED)) == NULL) |
849 return DMERR_MALLOC; | 884 return DMERR_MALLOC; |
850 | 885 |
851 handle->fops = &dfMemIOFileOps; | 886 handle->fops = &dfMemIOFileOps; |
852 handle->rawData = buf; | 887 handle->memData = buf; |
853 dmResourceInsert(lib, handle); | 888 dmResourceInsert(lib, handle); |
854 } | 889 } |
855 | 890 |
856 // Increase refcount | 891 // Increase refcount |
857 dmResourceRef(handle); | 892 dmResourceRef(handle); |