mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-15 00:08:11 -07:00
Merge remote-tracking branch 'origin/dev' into nestednonces
This commit is contained in:
@@ -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: {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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, ':');
|
||||
|
||||
Reference in New Issue
Block a user