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);