minIni_cache.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. // Open .ini file either from cache or from SD card
  64. bool ini_openwrite(const char *filename, INI_FILETYPE *fp)
  65. {
  66. #if INI_CACHE_SIZE > 0
  67. if (g_ini_cache.valid &&
  68. (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0))
  69. {
  70. fp->close();
  71. g_ini_cache.fp = fp;
  72. g_ini_cache.current_pos.position = 0;
  73. return true;
  74. }
  75. #endif
  76. return fp->open(SD.vol(), filename, O_WRONLY);
  77. }
  78. // Open .ini file either from cache or from SD card
  79. bool ini_openrewrite(const char *filename, INI_FILETYPE *fp)
  80. {
  81. #if INI_CACHE_SIZE > 0
  82. if (g_ini_cache.valid &&
  83. (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0))
  84. {
  85. fp->close();
  86. g_ini_cache.fp = fp;
  87. g_ini_cache.current_pos.position = 0;
  88. return true;
  89. }
  90. #endif
  91. return fp->open(SD.vol(), filename, O_RDWR);
  92. }
  93. void ini_rename(const char * old_name, const char *new_name)
  94. {
  95. SD.rename(old_name, new_name);
  96. invalidate_ini_cache();
  97. }
  98. // Close previously opened file
  99. bool ini_close(INI_FILETYPE *fp)
  100. {
  101. #if INI_CACHE_SIZE > 0
  102. if (g_ini_cache.fp == fp)
  103. {
  104. g_ini_cache.fp = NULL;
  105. return true;
  106. }
  107. else
  108. #endif
  109. {
  110. return fp->close();
  111. }
  112. }
  113. // Read a single line from cache or from SD card
  114. bool ini_read(char *buffer, int size, INI_FILETYPE *fp)
  115. {
  116. #if INI_CACHE_SIZE > 0
  117. if (g_ini_cache.fp == fp)
  118. {
  119. // Read one line from cache
  120. uint32_t srcpos = g_ini_cache.current_pos.position;
  121. int dstpos = 0;
  122. while (srcpos < g_ini_cache.filelen &&
  123. dstpos < size - 1)
  124. {
  125. char b = g_ini_cache.cachedata[srcpos++];
  126. buffer[dstpos++] = b;
  127. if (b == '\n') break;
  128. }
  129. buffer[dstpos] = 0;
  130. g_ini_cache.current_pos.position = srcpos;
  131. return dstpos > 0;
  132. }
  133. else
  134. #endif
  135. {
  136. // Read from SD card
  137. return fp->fgets(buffer, size) > 0;
  138. }
  139. }
  140. // Write to the card and invalidate the cache.
  141. bool ini_write(char *buffer, INI_FILETYPE *fp)
  142. {
  143. if(fp->write(buffer) > 0)
  144. {
  145. invalidate_ini_cache();
  146. return true;
  147. }
  148. else
  149. return false;
  150. }
  151. // Get the position inside the file
  152. void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos)
  153. {
  154. #if INI_CACHE_SIZE > 0
  155. if (g_ini_cache.fp == fp)
  156. {
  157. *pos = g_ini_cache.current_pos;
  158. }
  159. else
  160. #endif
  161. {
  162. fp->fgetpos(pos);
  163. }
  164. }
  165. // Go back to previously saved position
  166. void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos)
  167. {
  168. #if INI_CACHE_SIZE > 0
  169. if (g_ini_cache.fp == fp)
  170. {
  171. g_ini_cache.current_pos = *pos;
  172. }
  173. else
  174. #endif
  175. {
  176. fp->fsetpos(pos);
  177. }
  178. }