minIni_cache.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Custom .ini file access caching layer for minIni.
  2. // This reduces boot delay by only reading the ini file once
  3. // after boot or SD-card removal.
  4. #include <minGlue.h>
  5. #include <SdFat.h>
  6. // This can be overridden in platformio.ini
  7. // Set to 0 to disable the cache.
  8. #ifndef INI_CACHE_SIZE
  9. #define INI_CACHE_SIZE 4096
  10. #endif
  11. // Use the SdFs instance from main program
  12. extern SdFs SD;
  13. static struct {
  14. bool valid;
  15. INI_FILETYPE *fp;
  16. #if INI_CACHE_SIZE > 0
  17. const char *filename;
  18. uint32_t filelen;
  19. INI_FILEPOS current_pos;
  20. char cachedata[INI_CACHE_SIZE];
  21. #endif
  22. } g_ini_cache;
  23. // Invalidate any cached file contents
  24. void invalidate_ini_cache()
  25. {
  26. g_ini_cache.valid = false;
  27. g_ini_cache.fp = NULL;
  28. }
  29. // Read the config file into RAM
  30. void reload_ini_cache(const char *filename)
  31. {
  32. g_ini_cache.valid = false;
  33. g_ini_cache.fp = NULL;
  34. #if INI_CACHE_SIZE > 0
  35. g_ini_cache.filename = filename;
  36. FsFile config = SD.open(filename, O_RDONLY);
  37. g_ini_cache.filelen = config.fileSize();
  38. if (config.isOpen() && g_ini_cache.filelen <= INI_CACHE_SIZE)
  39. {
  40. if (config.read(g_ini_cache.cachedata, g_ini_cache.filelen) == g_ini_cache.filelen)
  41. {
  42. g_ini_cache.valid = true;
  43. }
  44. }
  45. config.close();
  46. #endif
  47. }
  48. // Open .ini file either from cache or from SD card
  49. bool ini_openread(const char *filename, INI_FILETYPE *fp)
  50. {
  51. #if INI_CACHE_SIZE > 0
  52. if (g_ini_cache.valid &&
  53. (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0))
  54. {
  55. fp->close();
  56. g_ini_cache.fp = fp;
  57. g_ini_cache.current_pos.position = 0;
  58. return true;
  59. }
  60. #endif
  61. return fp->open(SD.vol(), filename, O_RDONLY);
  62. }
  63. // Close previously opened file
  64. bool ini_close(INI_FILETYPE *fp)
  65. {
  66. #if INI_CACHE_SIZE > 0
  67. if (g_ini_cache.fp == fp)
  68. {
  69. g_ini_cache.fp = NULL;
  70. return true;
  71. }
  72. else
  73. #endif
  74. {
  75. return fp->close();
  76. }
  77. }
  78. // Read a single line from cache or from SD card
  79. bool ini_read(char *buffer, int size, INI_FILETYPE *fp)
  80. {
  81. #if INI_CACHE_SIZE > 0
  82. if (g_ini_cache.fp == fp)
  83. {
  84. // Read one line from cache
  85. uint32_t srcpos = g_ini_cache.current_pos.position;
  86. int dstpos = 0;
  87. while (srcpos < g_ini_cache.filelen &&
  88. dstpos < size - 1)
  89. {
  90. char b = g_ini_cache.cachedata[srcpos++];
  91. buffer[dstpos++] = b;
  92. if (b == '\n') break;
  93. }
  94. buffer[dstpos] = 0;
  95. g_ini_cache.current_pos.position = srcpos;
  96. return dstpos > 0;
  97. }
  98. else
  99. #endif
  100. {
  101. // Read from SD card
  102. return fp->fgets(buffer, size) > 0;
  103. }
  104. }
  105. // Get the position inside the file
  106. void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos)
  107. {
  108. #if INI_CACHE_SIZE > 0
  109. if (g_ini_cache.fp == fp)
  110. {
  111. *pos = g_ini_cache.current_pos;
  112. }
  113. else
  114. #endif
  115. {
  116. fp->fgetpos(pos);
  117. }
  118. }
  119. // Go back to previously saved position
  120. void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos)
  121. {
  122. #if INI_CACHE_SIZE > 0
  123. if (g_ini_cache.fp == fp)
  124. {
  125. g_ini_cache.current_pos = *pos;
  126. }
  127. else
  128. #endif
  129. {
  130. fp->fsetpos(pos);
  131. }
  132. }