You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.3KB

  1. #include "mkv-buffer.h"
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #if defined(_WIN32) || defined(_WIN64)
  6. #define fseek64 _fseeki64
  7. #define ftell64 _ftelli64
  8. #elif defined(OS_LINUX)
  9. #define fseek64 fseeko64
  10. #define ftell64 ftello64
  11. #else
  12. #define fseek64 fseek
  13. #define ftell64 ftell
  14. #endif
  15. static int mkv_file_read(void* fp, void* data, uint64_t bytes)
  16. {
  17. if (bytes == fread(data, 1, bytes, (FILE*)fp))
  18. return 0;
  19. return 0 != ferror((FILE*)fp) ? ferror((FILE*)fp) : -1 /*EOF*/;
  20. }
  21. static int mkv_file_write(void* fp, const void* data, uint64_t bytes)
  22. {
  23. return bytes == fwrite(data, 1, bytes, (FILE*)fp) ? 0 : ferror((FILE*)fp);
  24. }
  25. static int mkv_file_seek(void* fp, int64_t offset)
  26. {
  27. return fseek64((FILE*)fp, offset, offset >= 0 ? SEEK_SET : SEEK_END);
  28. }
  29. static int64_t mkv_file_tell(void* fp)
  30. {
  31. return ftell64((FILE*)fp);
  32. }
  33. static int mkv_file_cache_read(void* fp, void* data, uint64_t bytes)
  34. {
  35. uint8_t* p = (uint8_t*)data;
  36. struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
  37. while (bytes > 0)
  38. {
  39. assert(file->off <= file->len);
  40. if (file->off >= file->len)
  41. {
  42. if (bytes >= sizeof(file->ptr))
  43. {
  44. if (bytes == fread(p, 1, bytes, file->fp))
  45. {
  46. file->tell += bytes;
  47. return 0;
  48. }
  49. return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/;
  50. }
  51. else
  52. {
  53. file->off = 0;
  54. file->len = fread(file->ptr, 1, sizeof(file->ptr), file->fp);
  55. if (file->len < 1)
  56. return 0 != ferror(file->fp) ? ferror(file->fp) : -1 /*EOF*/;
  57. }
  58. }
  59. if (file->off < file->len)
  60. {
  61. unsigned int n = file->len - file->off;
  62. n = n > bytes ? bytes : n;
  63. memcpy(p, file->ptr + file->off, n);
  64. file->tell += n;
  65. file->off += n;
  66. bytes -= n;
  67. p += n;
  68. }
  69. }
  70. return 0;
  71. }
  72. static int mkv_file_cache_write(void* fp, const void* data, uint64_t bytes)
  73. {
  74. struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
  75. file->tell += bytes;
  76. if (file->off + bytes < sizeof(file->ptr))
  77. {
  78. memcpy(file->ptr + file->off, data, bytes);
  79. file->off += bytes;
  80. return 0;
  81. }
  82. // write buffer
  83. if (file->off > 0)
  84. {
  85. if (file->off != fwrite(file->ptr, 1, file->off, file->fp))
  86. return ferror(file->fp);
  87. file->off = 0; // clear buffer
  88. }
  89. // write data;
  90. return bytes == fwrite(data, 1, bytes, file->fp) ? 0 : ferror(file->fp);
  91. }
  92. static int mkv_file_cache_seek(void* fp, int64_t offset)
  93. {
  94. int r;
  95. struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
  96. if (offset != file->tell)
  97. {
  98. if (file->off > file->len)
  99. {
  100. // write bufferred data
  101. if (file->off != fwrite(file->ptr, 1, file->off, file->fp))
  102. return ferror(file->fp);
  103. }
  104. file->off = file->len = 0;
  105. r = fseek64(file->fp, offset, offset >= 0 ? SEEK_SET : SEEK_END);
  106. file->tell = ftell64(file->fp);
  107. return r;
  108. }
  109. return 0;
  110. }
  111. static int64_t mkv_file_cache_tell(void* fp)
  112. {
  113. struct mkv_file_cache_t* file = (struct mkv_file_cache_t*)fp;
  114. if (ftell64(file->fp) != file->tell + (int)(file->len - file->off))
  115. return -1;
  116. return (int64_t)file->tell;
  117. //return ftell64(file->fp);
  118. }
  119. const struct mkv_buffer_t* mkv_file_buffer(void)
  120. {
  121. static struct mkv_buffer_t s_io = {
  122. mkv_file_read,
  123. mkv_file_write,
  124. mkv_file_seek,
  125. mkv_file_tell,
  126. };
  127. return &s_io;
  128. }
  129. const struct mkv_buffer_t* mkv_file_cache_buffer(void)
  130. {
  131. static struct mkv_buffer_t s_io = {
  132. mkv_file_cache_read,
  133. mkv_file_cache_write,
  134. mkv_file_cache_seek,
  135. mkv_file_cache_tell,
  136. };
  137. return &s_io;
  138. }