libDaisy
Hardware Library for Daisy
Loading...
Searching...
No Matches
FileTable.h
Go to the documentation of this file.
1#pragma once
2#pragma once
3#include <cctype>
4#include <cstring>
5
6#include "ff.h"
7
8namespace daisy
9{
15template <size_t max_slots>
17{
18 public:
19 static constexpr const size_t kMaxCustomFileNameLen = _MAX_LFN;
20 static constexpr const size_t kMaxFileSlots = max_slots;
21
23 void Clear()
24 {
25 for(auto &item : table)
26 {
27 std::fill(item.name, item.name + kMaxCustomFileNameLen, 0x00);
28 item.size = 0;
29 }
30 num_files_found = 0;
31 }
32
43 bool Fill(const char *path, const char *endswith = nullptr)
44 {
45 FRESULT res = FR_OK;
46 if(path == nullptr)
47 {
48 return false;
49 }
50 FILINFO fno;
51 res = f_opendir(&dir, path);
52 size_t cnt = 0;
53 if(res == FR_OK)
54 {
55 for(;;)
56 {
57 res = f_readdir(&dir, &fno);
58 if(fno.fname[0] == 0)
59 break; //< escape w/ no file
60 bool valid_file_attrs = !(fno.fattrib & AM_HID)
61 && !(fno.fattrib & AM_DIR)
62 && !(fno.fattrib & AM_SYS);
63
64 bool valid_size = fno.fsize > 0;
65
66 bool valid_name = false;
67 if(endswith != nullptr)
68 {
69 uint32_t suffix_len = strlen(endswith);
70 valid_name = strstr(fno.fname, endswith) != nullptr
71 && strlen(fno.fname) > suffix_len
72 && strlen(fno.fname) < kMaxCustomFileNameLen;
73 }
74 else
75 {
76 valid_name = strlen(fno.fname) < kMaxCustomFileNameLen;
77 }
78
79 if(valid_file_attrs && valid_size && valid_name)
80 {
81 // Copy this file into the slot of the table, and increment
82 strcpy(table[cnt].name, fno.fname);
83 table[cnt].size = fno.fsize;
84 cnt++;
85 }
86 if(cnt > kMaxFileSlots - 1)
87 break;
88 }
89 f_closedir(&dir);
90 }
91 num_files_found = cnt;
92 SortTable();
93 return res == FR_OK;
94 }
95
101 bool WriteLog(const char *log_file_name)
102 {
103 FRESULT res
104 = f_open(&file, log_file_name, (FA_CREATE_ALWAYS | FA_WRITE));
105 if(res == FR_OK)
106 {
107 if(num_files_found > 0)
108 {
109 for(size_t i = 0; i < num_files_found; i++)
110 {
111 char line_buff[kMaxCustomFileNameLen + 32];
112 std::fill(line_buff, line_buff + sizeof(line_buff), 0x00);
113 sprintf(line_buff,
114 "%d:\t%s\t%d bytes\n",
115 i + 1,
116 table[i].name,
117 table[i].size);
118 UINT bw = 0;
119 res = f_write(&file, line_buff, strlen(line_buff), &bw);
120 if(res != FR_OK)
121 {
122 return f_close(&file) == FR_OK;
123 }
124 }
125 }
126 else
127 {
128 const char *text = "No matching files found...";
129 UINT bw = 0;
130 res = f_write(&file, text, strlen(text), &bw);
131 }
132 f_close(&file);
133 }
134 return res == FR_OK;
135 }
136
138 inline bool IsFileInSlot(size_t idx) const { return table[idx].size > 0; }
139
141 inline size_t GetFileSize(size_t idx) const { return table[idx].size; }
142
144 inline const char *GetFileName(size_t idx) const { return table[idx].name; }
145
147 inline size_t GetNumFiles() const { return num_files_found; }
148
156 inline bool IsLoadPending() const { return load_pending_; }
157
158 inline void ClearLoadPending()
159 {
160 load_pending_ = false;
161 slot_for_load_save_ = -1;
162 }
163 inline void SetLoadPending(int slot)
164 {
165 load_pending_ = true;
166 slot_for_load_save_ = slot;
167 }
168
169 inline bool IsSavePending() const { return save_pending_; }
170
171 inline void ClearSavePending()
172 {
173 save_pending_ = false;
174 slot_for_load_save_ = -1;
175 }
176 inline void SetSavePending(int slot)
177 {
178 save_pending_ = true;
179 slot_for_load_save_ = slot;
180 }
181
182 inline int GetSlotForSaveLoad() const { return slot_for_load_save_; }
183
184 private:
185 struct FileInfo
186 {
187 char name[kMaxCustomFileNameLen];
188 size_t size;
189 };
190
192 void SortTable()
193 {
194 if(num_files_found < 2)
195 return;
196
197 for(size_t i = 1; i < num_files_found; ++i)
198 {
199 FileInfo key = table[i];
200 size_t j = i;
201 while(j > 0 && CaseInsensitiveCmp(table[j - 1].name, key.name) > 0)
202 {
203 table[j] = table[j - 1];
204 --j;
205 }
206 table[j] = key;
207 }
208 }
209
210 FIL file;
211 DIR dir;
212 FileInfo table[kMaxFileSlots];
213 size_t num_files_found;
214
215 // Flags for saving/loading of files (not the best place for these)
216 // but this saves adding more back-and-forth between the new UiPage
217 // and the actual diskio
218 bool load_pending_;
219 bool save_pending_;
220 int slot_for_load_save_;
221
222 // Internal helper for sorting files on to a known order.
223 static inline int CaseInsensitiveCmp(const char *a, const char *b)
224 {
225 // ASCII-only case fold adequate for FAT volume typical usage
226 unsigned char ca, cb;
227 while(*a && *b)
228 {
229 ca = static_cast<unsigned char>(*a);
230 cb = static_cast<unsigned char>(*b);
231 ca = static_cast<unsigned char>(std::tolower(ca));
232 cb = static_cast<unsigned char>(std::tolower(cb));
233 if(ca != cb)
234 return (ca < cb) ? -1 : 1;
235 ++a;
236 ++b;
237 }
238 if(*a == *b)
239 return 0;
240 return (*a == '\0') ? -1 : 1;
241 }
242};
243
244} // namespace daisy
Definition FileTable.h:17
size_t GetFileSize(size_t idx) const
Definition FileTable.h:141
void SetSavePending(int slot)
Definition FileTable.h:176
bool WriteLog(const char *log_file_name)
Definition FileTable.h:101
bool Fill(const char *path, const char *endswith=nullptr)
Definition FileTable.h:43
void Clear()
Definition FileTable.h:23
void SetLoadPending(int slot)
Definition FileTable.h:163
bool IsSavePending() const
Definition FileTable.h:169
void ClearSavePending()
Definition FileTable.h:171
static constexpr const size_t kMaxFileSlots
Definition FileTable.h:20
const char * GetFileName(size_t idx) const
Definition FileTable.h:144
bool IsLoadPending() const
Definition FileTable.h:156
int GetSlotForSaveLoad() const
Definition FileTable.h:182
bool IsFileInSlot(size_t idx) const
Definition FileTable.h:138
static constexpr const size_t kMaxCustomFileNameLen
Definition FileTable.h:19
size_t GetNumFiles() const
Definition FileTable.h:147
void ClearLoadPending()
Definition FileTable.h:158
#define _MAX_LFN
Definition ffconf.h:117
Hardware defines and helpers for daisy field platform.
Definition index.h:2