Просмотр исходного кода

[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>
Georgii Surkov 3 лет назад
Родитель
Сommit
61189c3c82

+ 26 - 0
applications/debug/unit_tests/flipper_format/flipper_format_test.c

@@ -57,6 +57,23 @@ static const char* test_data_win = "Filetype: Flipper File test\r\n"
                                    "Hex data: DE AD BE";
 
 #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
 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;
 // data created by flipper itself
 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) {
     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_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) {
     tests_setup();
     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_result_test);
     MU_RUN_TEST(flipper_format_multikey_test);
+    MU_RUN_TEST(flipper_format_oddities_test);
     tests_teardown();
 }
 

+ 38 - 25
lib/flipper_format/flipper_format_stream.c

@@ -4,6 +4,10 @@
 #include "flipper_format_stream.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) {
     size_t bytes_written = stream_write(stream, data, data_size);
     return bytes_written == data_size;
@@ -118,55 +122,64 @@ 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) {
-    furi_string_reset(value);
+    enum { LeadingSpace, ReadValue, TrailingSpace } state = LeadingSpace;
     const size_t buffer_size = 32;
     uint8_t buffer[buffer_size];
     bool result = false;
     bool error = false;
 
+    furi_string_reset(value);
+
     while(true) {
         size_t was_read = stream_read(stream, buffer, buffer_size);
 
         if(was_read == 0) {
-            // check EOF
-            if(stream_eof(stream) && furi_string_size(value) > 0) {
+            if(state != LeadingSpace && stream_eof(stream)) {
                 result = true;
                 *last = true;
-                break;
+            } else {
+                error = true;
             }
         }
 
         for(uint16_t i = 0; i < was_read; i++) {
-            uint8_t data = buffer[i];
-            if(data == flipper_format_eoln) {
-                if(furi_string_size(value) > 0) {
-                    if(!stream_seek(stream, i - was_read, StreamOffsetFromCurrent)) {
-                        error = true;
-                        break;
-                    }
+            const uint8_t data = buffer[i];
 
-                    result = true;
-                    *last = true;
+            if(state == LeadingSpace) {
+                if(flipper_format_stream_is_space(data)) {
+                    continue;
+                } else if(data == flipper_format_eoln) {
+                    stream_seek(stream, i - was_read, StreamOffsetFromCurrent);
+                    error = true;
                     break;
                 } else {
-                    error = true;
+                    state = ReadValue;
+                    furi_string_push_back(value, data);
                 }
-            } else if(data == ' ') {
-                if(furi_string_size(value) > 0) {
+            } 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;
-                        break;
+                    } else {
+                        result = true;
+                        *last = true;
                     }
-
-                    result = true;
-                    *last = false;
                     break;
+                } else {
+                    furi_string_push_back(value, data);
                 }
-
-            } else if(data == flipper_format_eolr) {
-                // Ignore
-            } else {
-                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;
             }
         }