romfs.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include <Arduino.h>
  2. #include "romfs.h"
  3. #include "romfs_files.h"
  4. #include <string.h>
  5. #include "tinf.h"
  6. const ROMFS::embedded_file *ROMFS::find(const char *fname)
  7. {
  8. for (const auto &f : files) {
  9. if (strcmp(fname, f.filename) == 0) {
  10. Serial.printf("ROMFS Returning '%s' size=%u len=%u\n",
  11. fname, f.size, strlen((const char *)f.contents));
  12. return &f;
  13. }
  14. }
  15. Serial.printf("ROMFS not found '%s'\n", fname);
  16. return nullptr;
  17. }
  18. bool ROMFS::exists(const char *fname)
  19. {
  20. return find(fname) != nullptr;
  21. }
  22. ROMFS_Stream *ROMFS::find_stream(const char *fname)
  23. {
  24. const auto *f = find(fname);
  25. if (!f) {
  26. return nullptr;
  27. }
  28. return new ROMFS_Stream(*f);
  29. }
  30. size_t ROMFS_Stream::size(void) const
  31. {
  32. return f.size;
  33. }
  34. const char *ROMFS_Stream::name(void) const
  35. {
  36. return f.filename;
  37. }
  38. int ROMFS_Stream::available(void)
  39. {
  40. return f.size - offset;
  41. }
  42. size_t ROMFS_Stream::read(uint8_t* buf, size_t size)
  43. {
  44. const auto avail = available();
  45. if (size > avail) {
  46. size = avail;
  47. }
  48. memcpy(buf, &f.contents[offset], size);
  49. offset += size;
  50. return size;
  51. }
  52. int ROMFS_Stream::peek(void)
  53. {
  54. if (offset >= f.size) {
  55. return -1;
  56. }
  57. return f.contents[offset];
  58. }
  59. int ROMFS_Stream::read(void)
  60. {
  61. if (offset >= f.size) {
  62. return -1;
  63. }
  64. return f.contents[offset++];
  65. }
  66. /*
  67. decompress and return a string
  68. */
  69. const char *ROMFS::find_string(const char *name)
  70. {
  71. const auto *f = find(name);
  72. if (!f) {
  73. return nullptr;
  74. }
  75. // last 4 bytes of gzip file are length of decompressed data
  76. const uint8_t *p = &f->contents[f->size-4];
  77. uint32_t decompressed_size = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
  78. uint8_t *decompressed_data = (uint8_t *)malloc(decompressed_size + 1);
  79. if (!decompressed_data) {
  80. return nullptr;
  81. }
  82. // explicitly null terimnate the data
  83. decompressed_data[decompressed_size] = 0;
  84. TINF_DATA *d = (TINF_DATA *)malloc(sizeof(TINF_DATA));
  85. if (!d) {
  86. ::free(decompressed_data);
  87. return nullptr;
  88. }
  89. uzlib_uncompress_init(d, NULL, 0);
  90. d->source = f->contents;
  91. d->source_limit = f->contents + f->size - 4;
  92. // assume gzip format
  93. int res = uzlib_gzip_parse_header(d);
  94. if (res != TINF_OK) {
  95. ::free(decompressed_data);
  96. ::free(d);
  97. return nullptr;
  98. }
  99. d->dest = decompressed_data;
  100. d->destSize = decompressed_size;
  101. // we don't check CRC, as it just wastes flash space for constant
  102. // ROMFS data
  103. res = uzlib_uncompress(d);
  104. ::free(d);
  105. if (res != TINF_OK) {
  106. ::free(decompressed_data);
  107. return nullptr;
  108. }
  109. return (const char *)decompressed_data;
  110. }