Mercurial > hg > th-libs
comparison th_ioctx.c @ 678:7e207f1023d9
Split stdio and memio stuff to separate files from th_stdio.c
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 29 Feb 2020 12:19:02 +0200 |
parents | fb4093ad1f7b |
children | dfc2c9f0577f |
comparison
equal
deleted
inserted
replaced
677:927772fb0745 | 678:7e207f1023d9 |
---|---|
6 * Please read file 'COPYING' for information on license and distribution. | 6 * Please read file 'COPYING' for information on license and distribution. |
7 */ | 7 */ |
8 #include "th_ioctx.h" | 8 #include "th_ioctx.h" |
9 #include "th_string.h" | 9 #include "th_string.h" |
10 #include "th_endian.h" | 10 #include "th_endian.h" |
11 #include <stdio.h> | |
12 | 11 |
13 | 12 |
14 static void th_io_update_atime(th_ioctx *ctx) | 13 static void th_io_update_atime(th_ioctx *ctx) |
15 { | 14 { |
16 ctx->atime = time(NULL); | 15 ctx->atime = time(NULL); |
359 | 358 |
360 TH_DEFINE_FUNC(le64, uint64_t, LE64) | 359 TH_DEFINE_FUNC(le64, uint64_t, LE64) |
361 TH_DEFINE_FUNC(be64, uint64_t, BE64) | 360 TH_DEFINE_FUNC(be64, uint64_t, BE64) |
362 | 361 |
363 #undef TH_DEFINE_FUNC | 362 #undef TH_DEFINE_FUNC |
364 | |
365 | |
366 // | |
367 // stdio wrappers for I/O contexts | |
368 // | |
369 #define CTX_FH ((FILE *) ctx->data) | |
370 | |
371 | |
372 static int th_stdio_fopen(th_ioctx *ctx) | |
373 { | |
374 ctx->data = (void *) fopen(ctx->filename, ctx->mode); | |
375 ctx->status = th_get_error(); | |
376 return (ctx->data != NULL) ? THERR_OK : THERR_FOPEN; | |
377 } | |
378 | |
379 | |
380 static void th_stdio_fclose(th_ioctx *ctx) | |
381 { | |
382 if (CTX_FH != NULL) | |
383 { | |
384 fclose(CTX_FH); | |
385 ctx->data = NULL; | |
386 } | |
387 } | |
388 | |
389 | |
390 static int th_stdio_ferror(th_ioctx *ctx) | |
391 { | |
392 return ctx->status; | |
393 } | |
394 | |
395 | |
396 static off_t th_stdio_ftell(th_ioctx *ctx) | |
397 { | |
398 return ftello(CTX_FH); | |
399 } | |
400 | |
401 | |
402 static int th_stdio_fseek(th_ioctx *ctx, const off_t pos, const int whence) | |
403 { | |
404 int ret = fseeko(CTX_FH, pos, whence); | |
405 ctx->status = th_get_error(); | |
406 return ret; | |
407 } | |
408 | |
409 | |
410 static int th_stdio_freset(th_ioctx *ctx) | |
411 { | |
412 if (CTX_FH != NULL) | |
413 return th_stdio_fseek(ctx, 0, SEEK_SET); | |
414 else | |
415 return THERR_OK; | |
416 } | |
417 | |
418 | |
419 static off_t th_stdio_fsize(th_ioctx *ctx) | |
420 { | |
421 off_t savePos, fileSize; | |
422 | |
423 // Check if the size is cached | |
424 if (ctx->size != 0) | |
425 return ctx->size; | |
426 | |
427 // Get file size | |
428 if ((savePos = th_stdio_ftell(ctx)) < 0) | |
429 return -1; | |
430 | |
431 if (th_stdio_fseek(ctx, 0, SEEK_END) != 0) | |
432 return -1; | |
433 | |
434 if ((fileSize = th_stdio_ftell(ctx)) < 0) | |
435 return -1; | |
436 | |
437 if (th_stdio_fseek(ctx, savePos, SEEK_SET) != 0) | |
438 return -1; | |
439 | |
440 ctx->size = fileSize; | |
441 return fileSize; | |
442 } | |
443 | |
444 | |
445 static BOOL th_stdio_feof(th_ioctx *ctx) | |
446 { | |
447 return feof(CTX_FH); | |
448 } | |
449 | |
450 | |
451 static int th_stdio_fgetc(th_ioctx *ctx) | |
452 { | |
453 int ret = fgetc(CTX_FH); | |
454 ctx->status = th_get_error(); | |
455 return ret; | |
456 } | |
457 | |
458 | |
459 static int th_stdio_fputc(int v, th_ioctx *ctx) | |
460 { | |
461 int ret = fputc(v, CTX_FH); | |
462 ctx->status = th_get_error(); | |
463 return ret; | |
464 } | |
465 | |
466 | |
467 static size_t th_stdio_fread(void *ptr, size_t size, size_t nmemb, th_ioctx *ctx) | |
468 { | |
469 size_t ret = fread(ptr, size, nmemb, CTX_FH); | |
470 ctx->status = th_get_error(); | |
471 return ret; | |
472 } | |
473 | |
474 | |
475 static size_t th_stdio_fwrite(const void *ptr, size_t size, size_t nmemb, th_ioctx *ctx) | |
476 { | |
477 size_t ret = fwrite(ptr, size, nmemb, CTX_FH); | |
478 ctx->status = th_get_error(); | |
479 return ret; | |
480 } | |
481 | |
482 | |
483 static char * th_stdio_fgets(char *str, int size, th_ioctx *ctx) | |
484 { | |
485 char *ret = fgets(str, size, CTX_FH); | |
486 ctx->status = th_get_error(); | |
487 return ret; | |
488 } | |
489 | |
490 | |
491 static int th_stdio_fputs(const char *str, th_ioctx *ctx) | |
492 { | |
493 int ret = fputs(str, CTX_FH); | |
494 ctx->status = th_get_error(); | |
495 return ret; | |
496 } | |
497 | |
498 | |
499 static int th_stdio_vfprintf(th_ioctx *ctx, const char *fmt, va_list ap) | |
500 { | |
501 int ret = vfprintf(CTX_FH, fmt, ap); | |
502 ctx->status = th_get_error(); | |
503 return ret; | |
504 } | |
505 | |
506 | |
507 const th_ioctx_ops th_stdio_io_ops = | |
508 { | |
509 "stdio", | |
510 | |
511 th_stdio_fopen, | |
512 th_stdio_fclose, | |
513 | |
514 th_stdio_freset, | |
515 th_stdio_ferror, | |
516 th_stdio_fseek, | |
517 th_stdio_fsize, | |
518 th_stdio_ftell, | |
519 th_stdio_feof, | |
520 th_stdio_fgetc, | |
521 th_stdio_fputc, | |
522 th_stdio_fread, | |
523 th_stdio_fwrite, | |
524 | |
525 th_stdio_fgets, | |
526 th_stdio_fputs, | |
527 th_stdio_vfprintf, | |
528 }; | |
529 | |
530 | |
531 static BOOL th_mem_realloc(th_ioctx *ctx, const size_t newSize) | |
532 { | |
533 size_t grow; | |
534 | |
535 if (ctx->maxSize > 0 && newSize > ctx->maxSize) | |
536 { | |
537 ctx->status = THERR_BOUNDS; | |
538 return FALSE; | |
539 } | |
540 | |
541 if (newSize < ctx->memAlloc) | |
542 return TRUE; | |
543 | |
544 grow = (ctx->minAlloc > 0) ? ctx->minAlloc : 8 * 1024; | |
545 if (newSize - ctx->memAlloc > grow) | |
546 grow += newSize - ctx->memAlloc; | |
547 | |
548 if (ctx->maxSize > 0 && ctx->memAlloc + grow >= ctx->maxSize) | |
549 { | |
550 ctx->status = THERR_BOUNDS; | |
551 return FALSE; | |
552 } | |
553 | |
554 ctx->memAlloc += grow; | |
555 if ((ctx->memData = th_realloc(ctx->memData, ctx->memAlloc)) == NULL) | |
556 { | |
557 ctx->status = THERR_MALLOC; | |
558 return FALSE; | |
559 } | |
560 | |
561 ctx->memSize = newSize; | |
562 | |
563 return TRUE; | |
564 } | |
565 | |
566 | |
567 static int th_mem_freset(th_ioctx *ctx) | |
568 { | |
569 ctx->memOffset = 0; | |
570 return THERR_OK; | |
571 } | |
572 | |
573 | |
574 static int th_mem_ferror(th_ioctx *ctx) | |
575 { | |
576 return ctx->status; | |
577 } | |
578 | |
579 | |
580 static int th_mem_fseek(th_ioctx *ctx, const off_t offset, const int whence) | |
581 { | |
582 off_t newPos; | |
583 | |
584 // Calculate the new position | |
585 switch (whence) | |
586 { | |
587 case SEEK_SET: | |
588 newPos = offset; | |
589 break; | |
590 | |
591 case SEEK_CUR: | |
592 newPos = ctx->memOffset + offset; | |
593 break; | |
594 | |
595 case SEEK_END: | |
596 newPos = ctx->memSize + offset; | |
597 break; | |
598 | |
599 default: | |
600 return -1; | |
601 } | |
602 | |
603 // Set the new position | |
604 ctx->memOffset = newPos; | |
605 | |
606 // Check the new position | |
607 if (newPos < 0) | |
608 return -1; | |
609 | |
610 //if (!th_mem_realloc(ctx, newPos)) | |
611 // return -1; | |
612 | |
613 return 0; | |
614 } | |
615 | |
616 | |
617 static off_t th_mem_fsize(th_ioctx *ctx) | |
618 { | |
619 return ctx->memSize; | |
620 } | |
621 | |
622 | |
623 static off_t th_mem_ftell(th_ioctx *ctx) | |
624 { | |
625 return ctx->memOffset; | |
626 } | |
627 | |
628 | |
629 static BOOL th_mem_feof(th_ioctx *ctx) | |
630 { | |
631 return ((size_t) ctx->memOffset) >= ctx->memSize; | |
632 } | |
633 | |
634 | |
635 static int th_mem_fgetc(th_ioctx *ctx) | |
636 { | |
637 // Check for EOF | |
638 if ((size_t) ctx->memOffset < ctx->memSize) | |
639 return ctx->memData[ctx->memOffset++]; | |
640 else | |
641 return EOF; | |
642 } | |
643 | |
644 | |
645 static size_t th_mem_fread(void *buf, size_t size, size_t nmemb, th_ioctx *ctx) | |
646 { | |
647 size_t length = size * nmemb; | |
648 | |
649 // Check if we can read the whole chunk | |
650 if (((size_t) ctx->memOffset + length) >= ctx->memSize) | |
651 { | |
652 nmemb = (ctx->memSize - ctx->memOffset) / size; | |
653 length = size * nmemb; | |
654 } | |
655 | |
656 memcpy(buf, ctx->memData + ctx->memOffset, length); | |
657 ctx->memOffset += length; | |
658 return nmemb; | |
659 } | |
660 | |
661 | |
662 static int th_mem_fputc(int ch, th_ioctx *ctx) | |
663 { | |
664 // Check for EOF | |
665 if (!th_mem_realloc(ctx, ctx->memOffset + 1)) | |
666 return EOF; | |
667 | |
668 ctx->memData[ctx->memOffset++] = ch; | |
669 return ch; | |
670 } | |
671 | |
672 | |
673 static size_t th_mem_fwrite(const void *buf, size_t size, size_t nmemb, th_ioctx *ctx) | |
674 { | |
675 size_t length = size * nmemb; | |
676 | |
677 // Check if we can write the whole chunk | |
678 if (!th_mem_realloc(ctx, ctx->memOffset + length)) | |
679 { | |
680 nmemb = (ctx->memSize - ctx->memOffset) / size; | |
681 length = size * nmemb; | |
682 } | |
683 | |
684 if (length > 0) | |
685 { | |
686 memcpy(ctx->memData + ctx->memOffset, buf, length); | |
687 ctx->memOffset += length; | |
688 } | |
689 return nmemb; | |
690 } | |
691 | |
692 | |
693 const th_ioctx_ops th_mem_io_ops = | |
694 { | |
695 "MemIO", | |
696 | |
697 NULL, | |
698 NULL, | |
699 | |
700 th_mem_freset, | |
701 th_mem_ferror, | |
702 th_mem_fseek, | |
703 th_mem_fsize, | |
704 th_mem_ftell, | |
705 th_mem_feof, | |
706 th_mem_fgetc, | |
707 th_mem_fputc, | |
708 th_mem_fread, | |
709 th_mem_fwrite, | |
710 | |
711 NULL, | |
712 NULL, | |
713 NULL | |
714 }; |