Merge remote-tracking branch 'origin/dev' into nestednonces

This commit is contained in:
Aleksandr Kutuzov
2024-09-07 13:47:07 +01:00
110 changed files with 2019 additions and 697 deletions
+8 -5
View File
@@ -1,5 +1,6 @@
#include <inttypes.h>
#include <toolbox/hex.h>
#include <toolbox/strint.h>
#include <core/check.h>
#include "flipper_format_stream.h"
#include "flipper_format_stream_i.h"
@@ -396,14 +397,16 @@ bool flipper_format_stream_read_value_line(
#endif
case FlipperStreamValueInt32: {
int32_t* data = _data;
scan_values = sscanf(furi_string_get_cstr(value), "%" PRIi32, &data[i]);
if(strint_to_int32(furi_string_get_cstr(value), NULL, &data[i], 10) ==
StrintParseNoError) {
scan_values = 1;
}
}; break;
case FlipperStreamValueUint32: {
uint32_t* data = _data;
// Minus sign is allowed in scanf() for unsigned numbers, resulting in unintentionally huge values with no error reported
if(!furi_string_start_with(value, "-")) {
scan_values =
sscanf(furi_string_get_cstr(value), "%" PRIu32, &data[i]);
if(strint_to_uint32(furi_string_get_cstr(value), NULL, &data[i], 10) ==
StrintParseNoError) {
scan_values = 1;
}
}; break;
case FlipperStreamValueHexUint64: {
+4 -2
View File
@@ -39,11 +39,12 @@ void protocol_gproxii_free(ProtocolGProxII* protocol) {
}
uint8_t* protocol_gproxii_get_data(ProtocolGProxII* proto) {
return proto->data;
return proto->decoded_data;
}
void protocol_gproxii_decoder_start(ProtocolGProxII* protocol) {
memset(protocol->data, 0, GPROXII_ENCODED_BYTE_FULL_SIZE);
memset(protocol->decoded_data, 0, GPROXII_DATA_SIZE);
protocol->last_short = false;
}
@@ -88,8 +89,9 @@ static bool protocol_gproxii_can_be_decoded(ProtocolGProxII* protocol) {
if(bit_lib_get_bits(protocol->data, 0, 6) != 0b111110) return false;
// Check always 0 parity on every 5th bit after preamble
if(bit_lib_test_parity(protocol->data, 5, GPROXII_ENCODED_BIT_SIZE, BitLibParityAlways0, 5))
if(!bit_lib_test_parity(protocol->data, 6, GPROXII_ENCODED_BIT_SIZE, BitLibParityAlways0, 5)) {
return false;
}
// Start GProx II decode
bit_lib_copy_bits(protocol->decoded_data, 0, GPROXII_ENCODED_BIT_SIZE, protocol->data, 6);
+13 -13
View File
@@ -4,6 +4,7 @@
#include <flipper_format/flipper_format.h>
#include <flipper_format/flipper_format_i.h>
#include <lib/subghz/devices/devices.h>
#include <lib/toolbox/strint.h>
#define TAG "SubGhzFileEncoderWorker"
@@ -45,27 +46,26 @@ void subghz_file_encoder_worker_add_level_duration(
}
bool subghz_file_encoder_worker_data_parse(SubGhzFileEncoderWorker* instance, const char* strStart) {
char* str1;
bool res = false;
// Line sample: "RAW_Data: -1, 2, -2..."
// Look for a key in the line
str1 = strstr(strStart, "RAW_Data: ");
// Look for the key in the line
char* str = strstr(strStart, "RAW_Data: ");
bool res = false;
if(str1 != NULL) {
if(str) {
// Skip key
str1 = strchr(str1, ' ');
str = strchr(str, ' ');
// Check that there is still an element in the line
while(strchr(str1, ' ') != NULL) {
str1 = strchr(str1, ' ');
// Skip space
str1 += 1;
subghz_file_encoder_worker_add_level_duration(instance, atoi(str1));
// Parse next element
int32_t duration;
while(strint_to_int32(str, &str, &duration, 10) == StrintParseNoError) {
subghz_file_encoder_worker_add_level_duration(instance, duration);
if(*str == ',') str++; // could also be `\0`
}
res = true;
}
return res;
}
+1
View File
@@ -29,6 +29,7 @@ env.Append(
File("stream/file_stream.h"),
File("stream/string_stream.h"),
File("stream/buffered_file_stream.h"),
File("strint.h"),
File("protocols/protocol_dict.h"),
File("pretty_format.h"),
File("hex.h"),
+5 -1
View File
@@ -1,5 +1,7 @@
#include "args.h"
#include "hex.h"
#include "strint.h"
#include "m-core.h"
size_t args_get_first_word_length(FuriString* args) {
size_t ws = furi_string_search_char(args, ' ');
@@ -21,7 +23,9 @@ bool args_read_int_and_trim(FuriString* args, int* value) {
return false;
}
if(sscanf(furi_string_get_cstr(args), "%d", value) == 1) {
int32_t temp;
if(strint_to_int32(furi_string_get_cstr(args), NULL, &temp, 10) == StrintParseNoError) {
*value = temp;
furi_string_right(args, cmd_length);
furi_string_trim(args);
return true;
+121
View File
@@ -0,0 +1,121 @@
#include "strint.h"
#include <string.h>
// Splitting out the actual parser helps reduce code size. The manually
// monomorphized `strint_to_*`s are just wrappers around this generic
// implementation.
/**
* @brief Converts a string to a `uint64_t` and an auxillary sign bit, checking
* the bounds of the integer.
* @param [in] str Input string
* @param [out] end Pointer to first character after the number in input string
* @param [out] abs_out Absolute part of result
* @param [out] negative_out Sign part of result (true=negative, false=positive)
* @param [in] base Integer base
* @param [in] max_abs_negative Largest permissible absolute part of result if
* the sign is negative
* @param [in] max_positive Largest permissible absolute part of result if the
* sign is positive
*/
StrintParseError strint_to_uint64_internal(
const char* str,
char** end,
uint64_t* abs_out,
bool* negative_out,
uint8_t base,
uint64_t max_abs_negative,
uint64_t max_positive) {
// skip whitespace
while(((*str >= '\t') && (*str <= '\r')) || *str == ' ') {
str++;
}
// read sign
bool negative = false;
if(*str == '+' || *str == '-') {
if(*str == '-') negative = true;
str++;
}
if(*str == '+' || *str == '-') return StrintParseSignError;
if(max_abs_negative == 0 && negative) return StrintParseSignError;
// infer base
// not assigning directly to `base' to permit prefixes with explicit bases
uint8_t inferred_base = 0;
if(strncasecmp(str, "0x", 2) == 0) {
inferred_base = 16;
str += 2;
} else if(strncasecmp(str, "0b", 2) == 0) {
inferred_base = 2;
str += 2;
} else if(*str == '0') {
inferred_base = 8;
str++;
} else {
inferred_base = 10;
}
if(base == 0) base = inferred_base;
// read digits
uint64_t limit = negative ? max_abs_negative : max_positive;
uint64_t mul_limit = limit / base;
uint64_t result = 0;
int read_total = 0;
while(*str != 0) {
int digit_value;
if(*str >= '0' && *str <= '9') {
digit_value = *str - '0';
} else if(*str >= 'A' && *str <= 'Z') {
digit_value = *str - 'A' + 10;
} else if(*str >= 'a' && *str <= 'z') {
digit_value = *str - 'a' + 10;
} else {
break;
}
if(digit_value >= base) {
break;
}
if(result > mul_limit) return StrintParseOverflowError;
result *= base;
if(result > limit - digit_value) return StrintParseOverflowError;
result += digit_value;
read_total++;
str++;
}
if(read_total == 0) {
if(inferred_base == 8) {
// there's just a single zero
result = 0;
} else {
return StrintParseAbsentError;
}
}
if(abs_out) *abs_out = result;
if(negative_out) *negative_out = negative;
if(end) *end = (char*)str; // rabbit hole: https://c-faq.com/ansi/constmismatch.html
return StrintParseNoError;
}
#define STRINT_MONO(name, ret_type, neg_abs_limit, pos_limit) \
StrintParseError name(const char* str, char** end, ret_type* out, uint8_t base) { \
uint64_t absolute; \
bool negative; \
StrintParseError err = strint_to_uint64_internal( \
str, end, &absolute, &negative, base, (neg_abs_limit), (pos_limit)); \
if(err) return err; \
if(out) *out = (negative ? (-(ret_type)absolute) : ((ret_type)absolute)); \
return StrintParseNoError; \
}
STRINT_MONO(strint_to_uint64, uint64_t, 0, UINT64_MAX)
STRINT_MONO(strint_to_int64, int64_t, (uint64_t)INT64_MAX + 1, INT64_MAX)
STRINT_MONO(strint_to_uint32, uint32_t, 0, UINT32_MAX)
STRINT_MONO(strint_to_int32, int32_t, (uint64_t)INT32_MAX + 1, INT32_MAX)
STRINT_MONO(strint_to_uint16, uint16_t, 0, UINT16_MAX)
STRINT_MONO(strint_to_int16, int16_t, (uint64_t)INT16_MAX + 1, INT16_MAX)
+70
View File
@@ -0,0 +1,70 @@
/**
* @file strint.h
* Performs conversions between strings and integers.
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** String to integer conversion error */
typedef enum {
StrintParseNoError, //!< Conversion performed successfully
StrintParseSignError, //!< Multiple leading `+` or `-` characters, or leading `-` character if the type is unsigned
StrintParseAbsentError, //!< No valid digits after the leading whitespace, sign and prefix
StrintParseOverflowError, //!< Result does not fit in the requested type
} StrintParseError;
/** See `strint_to_uint32` */
StrintParseError strint_to_uint64(const char* str, char** end, uint64_t* out, uint8_t base);
/** See `strint_to_uint32` */
StrintParseError strint_to_int64(const char* str, char** end, int64_t* out, uint8_t base);
/** Converts a string to a `uint32_t`
*
* @param[in] str Input string
* @param[out] end Pointer to first character after the number in input string
* @param[out] out Parse result
* @param[in] base Integer base
*
* @return Parse error
*
* Parses the number in the input string. The number may be surrounded by
* whitespace characters to the left and any non-digit characters to the right.
* What's considered a digit is determined by the input base in the following
* order: `0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ`. The number may be prefixed
* with either a `+` or a `-` to indicate its sign. The pointer to the first
* character after the leading whitespace, allowed prefixes and digits is
* assigned to `end`.
*
* If the input base is 0, the base is inferred from the leading characters of
* the number:
* - If it starts with `0x`, it's read in base 16;
* - If it starts with a `0`, it's read in base 8;
* - If it starts with `0b`, it's read in base 2.
* - Otherwise, it's read in base 10.
*
* For a description of the return codes, see `StrintParseError`. If the return
* code is something other than `StrintParseNoError`, the values at `end` and
* `out` are unaltered.
*/
StrintParseError strint_to_uint32(const char* str, char** end, uint32_t* out, uint8_t base);
/** See `strint_to_uint32` */
StrintParseError strint_to_int32(const char* str, char** end, int32_t* out, uint8_t base);
/** See `strint_to_uint32` */
StrintParseError strint_to_uint16(const char* str, char** end, uint16_t* out, uint8_t base);
/** See `strint_to_uint32` */
StrintParseError strint_to_int16(const char* str, char** end, int16_t* out, uint8_t base);
#ifdef __cplusplus
}
#endif
@@ -1,4 +1,4 @@
#include "lfs_backup.h"
#include "int_backup.h"
#include <toolbox/tar/tar_archive.h>
@@ -9,7 +9,7 @@
#include <desktop/desktop_settings_filename.h>
#include <notification/notification_settings_filename.h>
#define LFS_BACKUP_DEFAULT_LOCATION EXT_PATH(LFS_BACKUP_DEFAULT_FILENAME)
#define INT_BACKUP_DEFAULT_LOCATION EXT_PATH(INT_BACKUP_DEFAULT_FILENAME)
static void backup_name_converter(FuriString* filename) {
if(furi_string_empty(filename) || (furi_string_get_char(filename, 0) == '.')) {
@@ -34,18 +34,18 @@ static void backup_name_converter(FuriString* filename) {
}
}
bool lfs_backup_create(Storage* storage, const char* destination) {
bool int_backup_create(Storage* storage, const char* destination) {
const char* final_destination =
destination && strlen(destination) ? destination : LFS_BACKUP_DEFAULT_LOCATION;
destination && strlen(destination) ? destination : INT_BACKUP_DEFAULT_LOCATION;
return storage_int_backup(storage, final_destination) == FSE_OK;
}
bool lfs_backup_exists(Storage* storage, const char* source) {
const char* final_source = source && strlen(source) ? source : LFS_BACKUP_DEFAULT_LOCATION;
bool int_backup_exists(Storage* storage, const char* source) {
const char* final_source = source && strlen(source) ? source : INT_BACKUP_DEFAULT_LOCATION;
return storage_common_stat(storage, final_source, NULL) == FSE_OK;
}
bool lfs_backup_unpack(Storage* storage, const char* source) {
const char* final_source = source && strlen(source) ? source : LFS_BACKUP_DEFAULT_LOCATION;
bool int_backup_unpack(Storage* storage, const char* source) {
const char* final_source = source && strlen(source) ? source : INT_BACKUP_DEFAULT_LOCATION;
return storage_int_restore(storage, final_source, backup_name_converter) == FSE_OK;
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <stdbool.h>
#include <storage/storage.h>
#define INT_BACKUP_DEFAULT_FILENAME "backup.tar"
#ifdef __cplusplus
extern "C" {
#endif
bool int_backup_create(Storage* storage, const char* destination);
bool int_backup_exists(Storage* storage, const char* source);
bool int_backup_unpack(Storage* storage, const char* source);
#ifdef __cplusplus
}
#endif
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#include <stdbool.h>
#include <storage/storage.h>
#define LFS_BACKUP_DEFAULT_FILENAME "backup.tar"
#ifdef __cplusplus
extern "C" {
#endif
bool lfs_backup_create(Storage* storage, const char* destination);
bool lfs_backup_exists(Storage* storage, const char* source);
bool lfs_backup_unpack(Storage* storage, const char* source);
#ifdef __cplusplus
}
#endif
+7 -1
View File
@@ -1,6 +1,7 @@
#include "manifest.h"
#include <toolbox/stream/buffered_file_stream.h>
#include <toolbox/strint.h>
#include <toolbox/hex.h>
struct ResourceManifestReader {
@@ -97,7 +98,12 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res
furi_string_right(
resource_manifest->linebuf, sizeof(resource_manifest->entry.hash) * 2 + 1);
resource_manifest->entry.size = atoi(furi_string_get_cstr(resource_manifest->linebuf));
if(strint_to_uint32(
furi_string_get_cstr(resource_manifest->linebuf),
NULL,
&resource_manifest->entry.size,
10) != StrintParseNoError)
break;
/* Remove size */
size_t offs = furi_string_search_char(resource_manifest->linebuf, ':');