|
@@ -0,0 +1,147 @@
|
|
|
|
|
+// Custom .ini file access caching layer for minIni.
|
|
|
|
|
+// This reduces boot delay by only reading the ini file once
|
|
|
|
|
+// after boot or SD-card removal.
|
|
|
|
|
+
|
|
|
|
|
+#include <minGlue.h>
|
|
|
|
|
+#include <SdFat.h>
|
|
|
|
|
+
|
|
|
|
|
+// This can be overridden in platformio.ini
|
|
|
|
|
+// Set to 0 to disable the cache.
|
|
|
|
|
+#ifndef INI_CACHE_SIZE
|
|
|
|
|
+#define INI_CACHE_SIZE 4096
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+// Use the SdFs instance from main program
|
|
|
|
|
+extern SdFs SD;
|
|
|
|
|
+
|
|
|
|
|
+static struct {
|
|
|
|
|
+ bool valid;
|
|
|
|
|
+ INI_FILETYPE *fp;
|
|
|
|
|
+
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ const char *filename;
|
|
|
|
|
+ uint32_t filelen;
|
|
|
|
|
+ INI_FILEPOS current_pos;
|
|
|
|
|
+ char cachedata[INI_CACHE_SIZE];
|
|
|
|
|
+#endif
|
|
|
|
|
+} g_ini_cache;
|
|
|
|
|
+
|
|
|
|
|
+// Invalidate any cached file contents
|
|
|
|
|
+void invalidate_ini_cache()
|
|
|
|
|
+{
|
|
|
|
|
+ g_ini_cache.valid = false;
|
|
|
|
|
+ g_ini_cache.fp = NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Read the config file into RAM
|
|
|
|
|
+void reload_ini_cache(const char *filename)
|
|
|
|
|
+{
|
|
|
|
|
+ g_ini_cache.valid = false;
|
|
|
|
|
+ g_ini_cache.fp = NULL;
|
|
|
|
|
+
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ g_ini_cache.filename = filename;
|
|
|
|
|
+ FsFile config = SD.open(filename, O_RDONLY);
|
|
|
|
|
+ g_ini_cache.filelen = config.fileSize();
|
|
|
|
|
+ if (config.isOpen() && g_ini_cache.filelen <= INI_CACHE_SIZE)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (config.read(g_ini_cache.cachedata, g_ini_cache.filelen) == g_ini_cache.filelen)
|
|
|
|
|
+ {
|
|
|
|
|
+ g_ini_cache.valid = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ config.close();
|
|
|
|
|
+#endif
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Open .ini file either from cache or from SD card
|
|
|
|
|
+bool ini_openread(const char *filename, INI_FILETYPE *fp)
|
|
|
|
|
+{
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ if (g_ini_cache.valid &&
|
|
|
|
|
+ (filename == g_ini_cache.filename || strcmp(filename, g_ini_cache.filename) == 0))
|
|
|
|
|
+ {
|
|
|
|
|
+ fp->close();
|
|
|
|
|
+ g_ini_cache.fp = fp;
|
|
|
|
|
+ g_ini_cache.current_pos.position = 0;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return fp->open(SD.vol(), filename, O_RDONLY);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Close previously opened file
|
|
|
|
|
+bool ini_close(INI_FILETYPE *fp)
|
|
|
|
|
+{
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ if (g_ini_cache.fp == fp)
|
|
|
|
|
+ {
|
|
|
|
|
+ g_ini_cache.fp = NULL;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+#endif
|
|
|
|
|
+ {
|
|
|
|
|
+ return fp->close();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Read a single line from cache or from SD card
|
|
|
|
|
+bool ini_read(char *buffer, int size, INI_FILETYPE *fp)
|
|
|
|
|
+{
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ if (g_ini_cache.fp == fp)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Read one line from cache
|
|
|
|
|
+ uint32_t srcpos = g_ini_cache.current_pos.position;
|
|
|
|
|
+ int dstpos = 0;
|
|
|
|
|
+ while (srcpos < g_ini_cache.filelen &&
|
|
|
|
|
+ dstpos < size - 1)
|
|
|
|
|
+ {
|
|
|
|
|
+ char b = g_ini_cache.cachedata[srcpos++];
|
|
|
|
|
+ buffer[dstpos++] = b;
|
|
|
|
|
+
|
|
|
|
|
+ if (b == '\n') break;
|
|
|
|
|
+ }
|
|
|
|
|
+ buffer[dstpos] = 0;
|
|
|
|
|
+ g_ini_cache.current_pos.position = srcpos;
|
|
|
|
|
+ return dstpos > 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+#endif
|
|
|
|
|
+ {
|
|
|
|
|
+ // Read from SD card
|
|
|
|
|
+ return fp->fgets(buffer, size) > 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Get the position inside the file
|
|
|
|
|
+void ini_tell(INI_FILETYPE *fp, INI_FILEPOS *pos)
|
|
|
|
|
+{
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ if (g_ini_cache.fp == fp)
|
|
|
|
|
+ {
|
|
|
|
|
+ *pos = g_ini_cache.current_pos;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+#endif
|
|
|
|
|
+ {
|
|
|
|
|
+ fp->fgetpos(pos);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Go back to previously saved position
|
|
|
|
|
+void ini_seek(INI_FILETYPE *fp, INI_FILEPOS *pos)
|
|
|
|
|
+{
|
|
|
|
|
+#if INI_CACHE_SIZE > 0
|
|
|
|
|
+ if (g_ini_cache.fp == fp)
|
|
|
|
|
+ {
|
|
|
|
|
+ g_ini_cache.current_pos = *pos;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+#endif
|
|
|
|
|
+ {
|
|
|
|
|
+ fp->fsetpos(pos);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|