Skip to content

Commit af3ffec

Browse files
committed
Merge branch 'feat/add_FatFs_encoding_options_in_menuconfig' into 'master'
fatfs/add menuconfig options for different encodings See merge request idf/esp-idf!2112
2 parents 27bf18a + 99b8ae3 commit af3ffec

File tree

6 files changed

+166
-5
lines changed

6 files changed

+166
-5
lines changed

components/fatfs/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,23 @@ config FATFS_MAX_LFN
107107
help
108108
Maximum long filename length. Can be reduced to save RAM.
109109

110+
choice FATFS_API_ENCODING
111+
prompt "API character encoding"
112+
depends on !FATFS_LFN_NONE
113+
default FATFS_API_ENCODING_ANSI_OEM
114+
help
115+
Choose encoding for character and string arguments/returns when using
116+
FATFS APIs. The encoding of arguments will usually depend on text
117+
editor settings.
118+
119+
config FATFS_API_ENCODING_ANSI_OEM
120+
bool "API uses ANSI/OEM encoding"
121+
config FATFS_API_ENCODING_UTF_16
122+
bool "API uses UTF-16 encoding"
123+
config FATFS_API_ENCODING_UTF_8
124+
bool "API uses UTF-8 encoding"
125+
endchoice
126+
110127
config FATFS_FS_LOCK
111128
int "Number of simultaneously open files protected by lock function"
112129
default 0

components/fatfs/src/ffconf.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@
129129
/ ff_memfree() in ffsystem.c, need to be added to the project. */
130130

131131

132-
#define FF_LFN_UNICODE 0
132+
#ifdef CONFIG_FATFS_API_ENCODING_UTF_8
133+
#define FF_LFN_UNICODE 2
134+
#elif defined(CONFIG_FATFS_API_ENCODING_UTF_16)
135+
#define FF_LFN_UNICODE 1
136+
#else /* CONFIG_FATFS_API_ENCODING_ANSI_OEM */
137+
#define FF_LFN_UNICODE 0
138+
#endif
133139
/* This option switches the character encoding on the API when LFN is enabled.
134140
/
135141
/ 0: ANSI/OEM in current CP (TCHAR = char)
@@ -148,7 +154,7 @@
148154
/ on character encoding. When LFN is not enabled, these options have no effect. */
149155

150156

151-
#define FF_STRF_ENCODE 3
157+
#define FF_STRF_ENCODE 3
152158
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
153159
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
154160
/ This option selects assumption of character encoding ON THE FILE to be

components/fatfs/test/test_fatfs_common.c

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "test_fatfs_common.h"
3030

3131
const char* fatfs_test_hello_str = "Hello, World!\n";
32+
const char* fatfs_test_hello_str_utf = "世界,你好!\n";
3233

3334
void test_fatfs_create_file_with_text(const char* name, const char* text)
3435
{
@@ -84,6 +85,17 @@ void test_fatfs_read_file(const char* filename)
8485
TEST_ASSERT_EQUAL(0, fclose(f));
8586
}
8687

88+
void test_fatfs_read_file_utf_8(const char* filename)
89+
{
90+
FILE* f = fopen(filename, "r");
91+
TEST_ASSERT_NOT_NULL(f);
92+
char buf[64] = { 0 }; //Doubled buffer size to allow for longer UTF-8 strings
93+
int cb = fread(buf, 1, sizeof(buf), f);
94+
TEST_ASSERT_EQUAL(strlen(fatfs_test_hello_str_utf), cb);
95+
TEST_ASSERT_EQUAL(0, strcmp(fatfs_test_hello_str_utf, buf));
96+
TEST_ASSERT_EQUAL(0, fclose(f));
97+
}
98+
8799
void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count)
88100
{
89101
FILE** files = calloc(files_count, sizeof(FILE*));
@@ -337,6 +349,85 @@ void test_fatfs_opendir_readdir_rewinddir(const char* dir_prefix)
337349
TEST_ASSERT_EQUAL(0, closedir(dir));
338350
}
339351

352+
void test_fatfs_opendir_readdir_rewinddir_utf_8(const char* dir_prefix)
353+
{
354+
char name_dir_inner_file[64];
355+
char name_dir_inner[64];
356+
char name_dir_file3[64];
357+
char name_dir_file2[64];
358+
char name_dir_file1[64];
359+
360+
snprintf(name_dir_inner_file, sizeof(name_dir_inner_file), "%s/内部目录/内部文件.txt", dir_prefix);
361+
snprintf(name_dir_inner, sizeof(name_dir_inner), "%s/内部目录", dir_prefix);
362+
snprintf(name_dir_file3, sizeof(name_dir_file3), "%s/文件三.bin", dir_prefix);
363+
snprintf(name_dir_file2, sizeof(name_dir_file2), "%s/文件二.txt", dir_prefix);
364+
snprintf(name_dir_file1, sizeof(name_dir_file1), "%s/文件一.txt", dir_prefix);
365+
366+
unlink(name_dir_inner_file);
367+
rmdir(name_dir_inner);
368+
unlink(name_dir_file1);
369+
unlink(name_dir_file2);
370+
unlink(name_dir_file3);
371+
rmdir(dir_prefix);
372+
373+
TEST_ASSERT_EQUAL(0, mkdir(dir_prefix, 0755));
374+
test_fatfs_create_file_with_text(name_dir_file1, "一号\n");
375+
test_fatfs_create_file_with_text(name_dir_file2, "二号\n");
376+
test_fatfs_create_file_with_text(name_dir_file3, "\0一\0二\0三");
377+
TEST_ASSERT_EQUAL(0, mkdir(name_dir_inner, 0755));
378+
test_fatfs_create_file_with_text(name_dir_inner_file, "三号\n");
379+
380+
DIR* dir = opendir(dir_prefix);
381+
TEST_ASSERT_NOT_NULL(dir);
382+
int count = 0;
383+
const char* names[4];
384+
while(count < 4) {
385+
struct dirent* de = readdir(dir);
386+
if (!de) {
387+
break;
388+
}
389+
printf("found '%s'\n", de->d_name);
390+
if (strcasecmp(de->d_name, "文件一.txt") == 0) {
391+
TEST_ASSERT_TRUE(de->d_type == DT_REG);
392+
names[count] = "文件一.txt";
393+
++count;
394+
} else if (strcasecmp(de->d_name, "文件二.txt") == 0) {
395+
TEST_ASSERT_TRUE(de->d_type == DT_REG);
396+
names[count] = "文件二.txt";
397+
++count;
398+
} else if (strcasecmp(de->d_name, "内部目录") == 0) {
399+
TEST_ASSERT_TRUE(de->d_type == DT_DIR);
400+
names[count] = "内部目录";
401+
++count;
402+
} else if (strcasecmp(de->d_name, "文件三.bin") == 0) {
403+
TEST_ASSERT_TRUE(de->d_type == DT_REG);
404+
names[count] = "文件三.bin";
405+
++count;
406+
} else {
407+
TEST_FAIL_MESSAGE("unexpected directory entry");
408+
}
409+
}
410+
TEST_ASSERT_EQUAL(count, 4);
411+
412+
rewinddir(dir);
413+
struct dirent* de = readdir(dir);
414+
TEST_ASSERT_NOT_NULL(de);
415+
TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[0]));
416+
seekdir(dir, 3);
417+
de = readdir(dir);
418+
TEST_ASSERT_NOT_NULL(de);
419+
TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[3]));
420+
seekdir(dir, 1);
421+
de = readdir(dir);
422+
TEST_ASSERT_NOT_NULL(de);
423+
TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[1]));
424+
seekdir(dir, 2);
425+
de = readdir(dir);
426+
TEST_ASSERT_NOT_NULL(de);
427+
TEST_ASSERT_EQUAL(0, strcasecmp(de->d_name, names[2]));
428+
429+
TEST_ASSERT_EQUAL(0, closedir(dir));
430+
}
340431

341432
typedef struct {
342433
const char* filename;
@@ -452,7 +543,6 @@ void test_fatfs_concurrent(const char* filename_prefix)
452543
vSemaphoreDelete(args4.done);
453544
}
454545

455-
456546
void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_t file_size, bool write)
457547
{
458548
const size_t buf_count = file_size / buf_size;
@@ -483,4 +573,3 @@ void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_
483573
(write)?"Wrote":"Read", file_size, buf_size, t_s * 1e3,
484574
file_size / (1024.0f * 1024.0f * t_s));
485575
}
486-

components/fatfs/test/test_fatfs_common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,16 @@
3232

3333

3434
const char* fatfs_test_hello_str;
35+
const char* fatfs_test_hello_str_utf;
3536

3637
void test_fatfs_create_file_with_text(const char* name, const char* text);
3738

3839
void test_fatfs_overwrite_append(const char* filename);
3940

4041
void test_fatfs_read_file(const char* filename);
4142

43+
void test_fatfs_read_file_utf_8(const char* filename);
44+
4245
void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count);
4346

4447
void test_fatfs_lseek(const char* filename);
@@ -57,4 +60,6 @@ void test_fatfs_can_opendir(const char* path);
5760

5861
void test_fatfs_opendir_readdir_rewinddir(const char* dir_prefix);
5962

63+
void test_fatfs_opendir_readdir_rewinddir_utf_8(const char* dir_prefix);
64+
6065
void test_fatfs_rw_speed(const char* filename, void* buf, size_t buf_size, size_t file_size, bool write);

components/fatfs/test/test_fatfs_sdmmc.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static void test_teardown(void)
5050
}
5151

5252
static const char* test_filename = "/sdcard/hello.txt";
53+
static const char* test_filename_utf_8 = "/sdcard/测试文件.txt";
5354

5455
TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]")
5556
{
@@ -239,3 +240,25 @@ TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fat
239240
fclose(f);
240241
TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", wl_handle));
241242
}
243+
244+
/*
245+
* In FatFs menuconfig, set CONFIG_FATFS_API_ENCODING to UTF-8 and set the
246+
* Codepage to CP936 (Simplified Chinese) in order to run the following tests.
247+
* Ensure that the text editor is UTF-8 compatible when compiling these tests.
248+
*/
249+
#if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936)
250+
TEST_CASE("(SD) can read file using UTF-8 encoded strings", "[fatfs][ignore]")
251+
{
252+
test_setup();
253+
test_fatfs_create_file_with_text(test_filename_utf_8, fatfs_test_hello_str_utf);
254+
test_fatfs_read_file_utf_8(test_filename_utf_8);
255+
test_teardown();
256+
}
257+
258+
TEST_CASE("(SD) opendir, readdir, rewinddir, seekdir work as expected using UTF-8 encoded strings", "[fatfs][ignore]")
259+
{
260+
test_setup();
261+
test_fatfs_opendir_readdir_rewinddir_utf_8("/sdcard/目录");
262+
test_teardown();
263+
}
264+
#endif

components/fatfs/test/test_fatfs_spiflash.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]")
9696
test_teardown();
9797
}
9898

99-
10099
TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]")
101100
{
102101
test_setup();
@@ -175,3 +174,25 @@ TEST_CASE("(WL) write/read speed test", "[fatfs][wear_levelling]")
175174
free(buf);
176175
test_teardown();
177176
}
177+
178+
/*
179+
* In FatFs menuconfig, set CONFIG_FATFS_API_ENCODING to UTF-8 and set the
180+
* Codepage to CP936 (Simplified Chinese) in order to run the following tests.
181+
* Ensure that the text editor is UTF-8 compatible when compiling these tests.
182+
*/
183+
#if defined(CONFIG_FATFS_API_ENCODING_UTF_8) && (CONFIG_FATFS_CODEPAGE == 936)
184+
TEST_CASE("(WL) can read file with UTF-8 encoded strings", "[fatfs][wear_levelling]")
185+
{
186+
test_setup();
187+
test_fatfs_create_file_with_text("/spiflash/测试文件.txt", fatfs_test_hello_str_utf);
188+
test_fatfs_read_file_utf_8("/spiflash/测试文件.txt");
189+
test_teardown();
190+
}
191+
192+
TEST_CASE("(WL) opendir, readdir, rewinddir, seekdir work as expected using UTF-8 encoded strings", "[fatfs][wear_levelling]")
193+
{
194+
test_setup();
195+
test_fatfs_opendir_readdir_rewinddir_utf_8("/spiflash/目录");
196+
test_teardown();
197+
}
198+
#endif

0 commit comments

Comments
 (0)