[FL-2312] Flipper format: insert OR update (#1009)
* Flipper format: seek_to_end, key_exist * Flipper Format: insert_or_update
This commit is contained in:
parent
966b400f8b
commit
c42cce3c6c
@ -11,22 +11,30 @@ static const uint32_t test_version = 666;
|
||||
static const char* test_string_key = "String data";
|
||||
static const char* test_string_data = "String";
|
||||
static const char* test_string_updated_data = "New string";
|
||||
static const char* test_string_updated_2_data = "And some more";
|
||||
|
||||
static const char* test_int_key = "Int32 data";
|
||||
static const int32_t test_int_data[] = {1234, -6345, 7813, 0};
|
||||
static const int32_t test_int_updated_data[] = {-1337, 69};
|
||||
static const int32_t test_int_updated_2_data[] = {-3, -2, -1, 0, 1, 2, 3};
|
||||
|
||||
static const char* test_uint_key = "Uint32 data";
|
||||
static const uint32_t test_uint_data[] = {1234, 0, 5678, 9098, 7654321};
|
||||
static const uint32_t test_uint_updated_data[] = {8, 800, 555, 35, 35};
|
||||
static const uint32_t test_uint_updated_2_data[] = {20, 21};
|
||||
|
||||
static const char* test_float_key = "Float data";
|
||||
static const float test_float_data[] = {1.5f, 1000.0f};
|
||||
static const float test_float_updated_data[] = {1.2f};
|
||||
static const float test_float_updated_2_data[] = {0.01f, 0.0f, -51.6f};
|
||||
|
||||
static const char* test_hex_key = "Hex data";
|
||||
static const uint8_t test_hex_data[] = {0xDE, 0xAD, 0xBE};
|
||||
static const uint8_t test_hex_updated_data[] = {0xFE, 0xCA};
|
||||
static const uint8_t test_hex_updated_2_data[] = {0xCA, 0xCA, 0x05};
|
||||
|
||||
static const char* test_hex_new_key = "New Hex data";
|
||||
static const uint8_t test_hex_new_data[] = {0xFF, 0x6A, 0x91};
|
||||
|
||||
static const char* test_data_nix = "Filetype: Flipper Format test\n"
|
||||
"Version: 666\n"
|
||||
@ -59,7 +67,40 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
|
||||
|
||||
uint32_t count;
|
||||
|
||||
// key exist test
|
||||
size_t position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// stream seek to end test
|
||||
mu_check(flipper_format_seek_to_end(flipper_format));
|
||||
mu_assert_int_eq(
|
||||
stream_size(flipper_format_get_raw_stream(flipper_format)),
|
||||
stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// key exist test
|
||||
position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// rewind
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
|
||||
// key exist test
|
||||
position_before = stream_tell(flipper_format_get_raw_stream(flipper_format));
|
||||
mu_check(flipper_format_key_exist(flipper_format, test_hex_key));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
mu_check(!flipper_format_key_exist(flipper_format, "invalid key"));
|
||||
mu_assert_int_eq(position_before, stream_tell(flipper_format_get_raw_stream(flipper_format)));
|
||||
|
||||
// read test
|
||||
string_init(tmpstr);
|
||||
|
||||
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
|
||||
@ -94,6 +135,7 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// update data
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_update_string_cstr(
|
||||
flipper_format, test_string_key, test_string_updated_data));
|
||||
@ -106,6 +148,7 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
|
||||
mu_check(flipper_format_update_hex(
|
||||
flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_updated_data)));
|
||||
|
||||
// read updated data test
|
||||
uint32_t uint32_updated_data[COUNT_OF(test_uint_updated_data)];
|
||||
int32_t int32_updated_data[COUNT_OF(test_int_updated_data)];
|
||||
float float_updated_data[COUNT_OF(test_float_updated_data)];
|
||||
@ -149,9 +192,76 @@ MU_TEST_1(flipper_format_read_and_update_test, FlipperFormat* flipper_format) {
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// update data
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_insert_or_update_string_cstr(
|
||||
flipper_format, test_string_key, test_string_updated_2_data));
|
||||
mu_check(flipper_format_insert_or_update_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(test_int_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(test_uint_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(test_float_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_hex(
|
||||
flipper_format, test_hex_key, ARRAY_W_COUNT(test_hex_updated_2_data)));
|
||||
mu_check(flipper_format_insert_or_update_hex(
|
||||
flipper_format, test_hex_new_key, ARRAY_W_COUNT(test_hex_new_data)));
|
||||
|
||||
uint32_t uint32_updated_2_data[COUNT_OF(test_uint_updated_2_data)];
|
||||
int32_t int32_updated_2_data[COUNT_OF(test_int_updated_2_data)];
|
||||
float float_updated_2_data[COUNT_OF(test_float_updated_2_data)];
|
||||
uint8_t hex_updated_2_data[COUNT_OF(test_hex_updated_2_data)];
|
||||
uint8_t hex_new_data[COUNT_OF(test_hex_new_data)];
|
||||
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
string_init(tmpstr);
|
||||
|
||||
mu_check(flipper_format_read_header(flipper_format, tmpstr, &version));
|
||||
mu_assert_string_eq(test_filetype, string_get_cstr(tmpstr));
|
||||
mu_assert_int_eq(test_version, version);
|
||||
|
||||
mu_check(flipper_format_read_string(flipper_format, test_string_key, tmpstr));
|
||||
mu_assert_string_eq(test_string_updated_2_data, string_get_cstr(tmpstr));
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_int_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_int_updated_2_data), count);
|
||||
mu_check(flipper_format_read_int32(
|
||||
flipper_format, test_int_key, ARRAY_W_COUNT(int32_updated_2_data)));
|
||||
mu_check(memcmp(test_int_updated_2_data, ARRAY_W_BSIZE(int32_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_uint_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_uint_updated_2_data), count);
|
||||
mu_check(flipper_format_read_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_updated_2_data)));
|
||||
mu_check(memcmp(test_uint_updated_2_data, ARRAY_W_BSIZE(uint32_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_float_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_float_updated_2_data), count);
|
||||
mu_check(flipper_format_read_float(
|
||||
flipper_format, test_float_key, ARRAY_W_COUNT(float_updated_2_data)));
|
||||
mu_check(memcmp(test_float_updated_2_data, ARRAY_W_BSIZE(float_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_updated_2_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_hex(flipper_format, test_hex_key, ARRAY_W_COUNT(hex_updated_2_data)));
|
||||
mu_check(memcmp(test_hex_updated_2_data, ARRAY_W_BSIZE(hex_updated_2_data)) == 0);
|
||||
|
||||
mu_check(flipper_format_get_value_count(flipper_format, test_hex_new_key, &count));
|
||||
mu_assert_int_eq(COUNT_OF(test_hex_new_data), count);
|
||||
mu_check(
|
||||
flipper_format_read_hex(flipper_format, test_hex_new_key, ARRAY_W_COUNT(hex_new_data)));
|
||||
mu_check(memcmp(test_hex_new_data, ARRAY_W_BSIZE(hex_new_data)) == 0);
|
||||
|
||||
mu_check(!flipper_format_read_string(flipper_format, "Key that doesn't exist", tmpstr));
|
||||
|
||||
string_clear(tmpstr);
|
||||
|
||||
// delete key test
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(flipper_format_delete_key(flipper_format, test_uint_key));
|
||||
|
||||
// deleted key read test
|
||||
mu_check(flipper_format_rewind(flipper_format));
|
||||
mu_check(!flipper_format_read_uint32(
|
||||
flipper_format, test_uint_key, ARRAY_W_COUNT(uint32_updated_data)));
|
||||
|
@ -102,6 +102,20 @@ bool flipper_format_rewind(FlipperFormat* flipper_format) {
|
||||
return stream_rewind(flipper_format->stream);
|
||||
}
|
||||
|
||||
bool flipper_format_seek_to_end(FlipperFormat* flipper_format) {
|
||||
furi_assert(flipper_format);
|
||||
return stream_seek(flipper_format->stream, 0, StreamOffsetFromEnd);
|
||||
}
|
||||
|
||||
bool flipper_format_key_exist(FlipperFormat* flipper_format, const char* key) {
|
||||
size_t pos = stream_tell(flipper_format->stream);
|
||||
stream_seek(flipper_format->stream, 0, StreamOffsetFromStart);
|
||||
bool result = flipper_format_stream_seek_to_key(flipper_format->stream, key, false);
|
||||
stream_seek(flipper_format->stream, pos, StreamOffsetFromStart);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_read_header(
|
||||
FlipperFormat* flipper_format,
|
||||
string_t filetype,
|
||||
@ -320,7 +334,7 @@ bool flipper_format_update_string(FlipperFormat* flipper_format, const char* key
|
||||
FlipperStreamWriteData write_data = {
|
||||
.key = key,
|
||||
.type = FlipperStreamValueStr,
|
||||
.data = data,
|
||||
.data = string_get_cstr(data),
|
||||
.data_size = 1,
|
||||
};
|
||||
bool result = flipper_format_stream_delete_key_and_write(
|
||||
@ -408,3 +422,103 @@ bool flipper_format_update_hex(
|
||||
flipper_format->stream, &write_data, flipper_format->strict_mode);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_string(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
string_t data) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_string(flipper_format, key, data);
|
||||
} else {
|
||||
result = flipper_format_update_string(flipper_format, key, data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_string_cstr(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const char* data) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_string_cstr(flipper_format, key, data);
|
||||
} else {
|
||||
result = flipper_format_update_string_cstr(flipper_format, key, data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_uint32(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const uint32_t* data,
|
||||
const uint16_t data_size) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_uint32(flipper_format, key, data, data_size);
|
||||
} else {
|
||||
result = flipper_format_update_uint32(flipper_format, key, data, data_size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_int32(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const int32_t* data,
|
||||
const uint16_t data_size) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_int32(flipper_format, key, data, data_size);
|
||||
} else {
|
||||
result = flipper_format_update_int32(flipper_format, key, data, data_size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_float(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const float* data,
|
||||
const uint16_t data_size) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_float(flipper_format, key, data, data_size);
|
||||
} else {
|
||||
result = flipper_format_update_float(flipper_format, key, data, data_size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool flipper_format_insert_or_update_hex(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const uint8_t* data,
|
||||
const uint16_t data_size) {
|
||||
bool result = false;
|
||||
|
||||
if(!flipper_format_key_exist(flipper_format, key)) {
|
||||
flipper_format_seek_to_end(flipper_format);
|
||||
result = flipper_format_write_hex(flipper_format, key, data, data_size);
|
||||
} else {
|
||||
result = flipper_format_update_hex(flipper_format, key, data, data_size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -179,6 +179,22 @@ void flipper_format_set_strict_mode(FlipperFormat* flipper_format, bool strict_m
|
||||
*/
|
||||
bool flipper_format_rewind(FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Move the RW pointer at the end. Can be useful if you want to add some data after reading.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_seek_to_end(FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Check if the key exists.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @return true key exists
|
||||
* @return false key is not exists
|
||||
*/
|
||||
bool flipper_format_key_exist(FlipperFormat* flipper_format, const char* key);
|
||||
|
||||
/**
|
||||
* Read the header (file type and version).
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
@ -466,6 +482,89 @@ bool flipper_format_update_hex(
|
||||
const uint8_t* data,
|
||||
const uint16_t data_size);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to a string value, or adds the key and value if the key did not exist.
|
||||
* Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_string(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
string_t data);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to a string value, or adds the key and value if the key did not exist.
|
||||
* Plain C version.
|
||||
* Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_string_cstr(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const char* data);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to a uint32 array value, or adds the key and value if the key did not exist.
|
||||
* Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_uint32(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const uint32_t* data,
|
||||
const uint16_t data_size);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to a int32 array value, or adds the key and value if the key did not exist.
|
||||
* Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_int32(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const int32_t* data,
|
||||
const uint16_t data_size);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to a float array value, or adds the key and value if the key did not exist.
|
||||
* Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_float(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const float* data,
|
||||
const uint16_t data_size);
|
||||
|
||||
/**
|
||||
* Updates the value of the first matching key to an array of hex-formatted bytes, or adds the key and value if the key did not exist.
|
||||
*Sets the RW pointer to a position at the end of inserted data.
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param key Key
|
||||
* @param data Value
|
||||
* @return True on success
|
||||
*/
|
||||
bool flipper_format_insert_or_update_hex(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
const uint8_t* data,
|
||||
const uint16_t data_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -93,7 +93,7 @@ static bool flipper_format_stream_read_valid_key(Stream* stream, string_t key) {
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode) {
|
||||
bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode) {
|
||||
bool found = false;
|
||||
string_t read_key;
|
||||
|
||||
|
@ -18,6 +18,17 @@ extern "C" {
|
||||
*/
|
||||
bool flipper_format_stream_write_eol(Stream* stream);
|
||||
|
||||
/**
|
||||
* Seek to the key from the current position of the stream.
|
||||
* Position will be at the beginning of the value corresponding to the key, if the key is found,, or at the end of the stream.
|
||||
* @param stream
|
||||
* @param key
|
||||
* @param strict_mode
|
||||
* @return true key is found
|
||||
* @return false key is not found
|
||||
*/
|
||||
bool flipper_format_stream_seek_to_key(Stream* stream, const char* key, bool strict_mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user