[FL-2847] FFF trailing space fix (#1811)
* Improve whitespace handlilng in FFF * Add tests for odd fff user input * Adjust formatting Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
9bf11d9fd2
commit
61189c3c82
@ -57,6 +57,23 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n"
|
|||||||
"Hex data: DE AD BE";
|
"Hex data: DE AD BE";
|
||||||
|
|
||||||
#define READ_TEST_FLP "ff_flp.test"
|
#define READ_TEST_FLP "ff_flp.test"
|
||||||
|
#define READ_TEST_ODD "ff_oddities.test"
|
||||||
|
static const char* test_data_odd = "Filetype: Flipper File test\n"
|
||||||
|
// Tabs before newline
|
||||||
|
"Version: 666\t\t\n"
|
||||||
|
"# This is comment\n"
|
||||||
|
// Windows newline in a UNIX file
|
||||||
|
"String data: String\r\n"
|
||||||
|
// Trailing whitespace
|
||||||
|
"Int32 data: 1234 -6345 7813 0 \n"
|
||||||
|
// Extra whitespace
|
||||||
|
"Uint32 data: 1234 0 5678 9098 7654321 \n"
|
||||||
|
// Mixed whitespace
|
||||||
|
"Float data: 1.5\t \t1000.0\n"
|
||||||
|
// Leading tabs after key
|
||||||
|
"Bool data:\t\ttrue false\n"
|
||||||
|
// Mixed trailing whitespace
|
||||||
|
"Hex data: DE AD BE\t ";
|
||||||
|
|
||||||
// data created by user on linux machine
|
// data created by user on linux machine
|
||||||
static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
|
static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
|
||||||
@ -64,6 +81,8 @@ static const char* test_file_linux = TEST_DIR READ_TEST_NIX;
|
|||||||
static const char* test_file_windows = TEST_DIR READ_TEST_WIN;
|
static const char* test_file_windows = TEST_DIR READ_TEST_WIN;
|
||||||
// data created by flipper itself
|
// data created by flipper itself
|
||||||
static const char* test_file_flipper = TEST_DIR READ_TEST_FLP;
|
static const char* test_file_flipper = TEST_DIR READ_TEST_FLP;
|
||||||
|
// data containing odd user input
|
||||||
|
static const char* test_file_oddities = TEST_DIR READ_TEST_ODD;
|
||||||
|
|
||||||
static bool storage_write_string(const char* path, const char* data) {
|
static bool storage_write_string(const char* path, const char* data) {
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
@ -503,6 +522,12 @@ MU_TEST(flipper_format_multikey_test) {
|
|||||||
mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error");
|
mu_assert(test_read_multikey(TEST_DIR "ff_multiline.test"), "Multikey read test error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(flipper_format_oddities_test) {
|
||||||
|
mu_assert(
|
||||||
|
storage_write_string(test_file_oddities, test_data_odd), "Write test error [Oddities]");
|
||||||
|
mu_assert(test_read(test_file_linux), "Read test error [Oddities]");
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(flipper_format) {
|
MU_TEST_SUITE(flipper_format) {
|
||||||
tests_setup();
|
tests_setup();
|
||||||
MU_RUN_TEST(flipper_format_write_test);
|
MU_RUN_TEST(flipper_format_write_test);
|
||||||
@ -516,6 +541,7 @@ MU_TEST_SUITE(flipper_format) {
|
|||||||
MU_RUN_TEST(flipper_format_update_2_test);
|
MU_RUN_TEST(flipper_format_update_2_test);
|
||||||
MU_RUN_TEST(flipper_format_update_2_result_test);
|
MU_RUN_TEST(flipper_format_update_2_result_test);
|
||||||
MU_RUN_TEST(flipper_format_multikey_test);
|
MU_RUN_TEST(flipper_format_multikey_test);
|
||||||
|
MU_RUN_TEST(flipper_format_oddities_test);
|
||||||
tests_teardown();
|
tests_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
#include "flipper_format_stream.h"
|
#include "flipper_format_stream.h"
|
||||||
#include "flipper_format_stream_i.h"
|
#include "flipper_format_stream_i.h"
|
||||||
|
|
||||||
|
static inline bool flipper_format_stream_is_space(char c) {
|
||||||
|
return c == ' ' || c == '\t' || c == flipper_format_eolr;
|
||||||
|
}
|
||||||
|
|
||||||
static bool flipper_format_stream_write(Stream* stream, const void* data, size_t data_size) {
|
static bool flipper_format_stream_write(Stream* stream, const void* data, size_t data_size) {
|
||||||
size_t bytes_written = stream_write(stream, data, data_size);
|
size_t bytes_written = stream_write(stream, data, data_size);
|
||||||
return bytes_written == data_size;
|
return bytes_written == data_size;
|
||||||
@ -118,56 +122,65 @@ bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool str
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool flipper_format_stream_read_value(Stream* stream, FuriString* value, bool* last) {
|
static bool flipper_format_stream_read_value(Stream* stream, FuriString* value, bool* last) {
|
||||||
furi_string_reset(value);
|
enum { LeadingSpace, ReadValue, TrailingSpace } state = LeadingSpace;
|
||||||
const size_t buffer_size = 32;
|
const size_t buffer_size = 32;
|
||||||
uint8_t buffer[buffer_size];
|
uint8_t buffer[buffer_size];
|
||||||
bool result = false;
|
bool result = false;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
|
furi_string_reset(value);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
size_t was_read = stream_read(stream, buffer, buffer_size);
|
size_t was_read = stream_read(stream, buffer, buffer_size);
|
||||||
|
|
||||||
if(was_read == 0) {
|
if(was_read == 0) {
|
||||||
// check EOF
|
if(state != LeadingSpace && stream_eof(stream)) {
|
||||||
if(stream_eof(stream) && furi_string_size(value) > 0) {
|
|
||||||
result = true;
|
result = true;
|
||||||
*last = true;
|
*last = true;
|
||||||
break;
|
} else {
|
||||||
|
error = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint16_t i = 0; i < was_read; i++) {
|
for(uint16_t i = 0; i < was_read; i++) {
|
||||||
uint8_t data = buffer[i];
|
const uint8_t data = buffer[i];
|
||||||
if(data == flipper_format_eoln) {
|
|
||||||
if(furi_string_size(value) > 0) {
|
if(state == LeadingSpace) {
|
||||||
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
|
if(flipper_format_stream_is_space(data)) {
|
||||||
|
continue;
|
||||||
|
} else if(data == flipper_format_eoln) {
|
||||||
|
stream_seek(stream, i - was_read, StreamOffsetFromCurrent);
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
state = ReadValue;
|
||||||
|
furi_string_push_back(value, data);
|
||||||
}
|
}
|
||||||
|
} else if(state == ReadValue) {
|
||||||
|
if(flipper_format_stream_is_space(data)) {
|
||||||
|
state = TrailingSpace;
|
||||||
|
} else if(data == flipper_format_eoln) {
|
||||||
|
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
|
||||||
|
error = true;
|
||||||
|
} else {
|
||||||
result = true;
|
result = true;
|
||||||
*last = true;
|
*last = true;
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
error = true;
|
|
||||||
}
|
}
|
||||||
} else if(data == ' ') {
|
|
||||||
if(furi_string_size(value) > 0) {
|
|
||||||
if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
|
|
||||||
error = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
*last = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(data == flipper_format_eolr) {
|
|
||||||
// Ignore
|
|
||||||
} else {
|
} else {
|
||||||
furi_string_push_back(value, data);
|
furi_string_push_back(value, data);
|
||||||
}
|
}
|
||||||
|
} else if(state == TrailingSpace) {
|
||||||
|
if(flipper_format_stream_is_space(data)) {
|
||||||
|
continue;
|
||||||
|
} else if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
|
||||||
|
error = true;
|
||||||
|
} else {
|
||||||
|
*last = (data == flipper_format_eoln);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(error || result) break;
|
if(error || result) break;
|
||||||
|
Loading…
Reference in New Issue
Block a user