[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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Georgii Surkov
						Georgii Surkov