Added lfs_* utils for memcmp/memcpy/memxor/strcmp/strspn/etc
Added:
name builtin? string.h?
lfs_memcmp y y
lfs_memcpy y y
lfs_memmove y y
lfs_memset y y
lfs_memchr y
lfs_memcchr (I wish!)
lfs_memxor
lfs_strlen y
lfs_strcmp y
lfs_strcpy y
lfs_strchr y
lfs_strcchr
lfs_strspn y
lfs_strcspn y
The intention of these is _not_ to try anything better than the stdlib,
but to allow users/integrators to override these functions if string.h
or stdlib.h is not available.
Well... The original motivation was just to add lfs_memcchr to
lfs_utils.h, which is useful for checking if a memory is all zeros, but
then things got a bit out of hand... Oh well, flexibility is good right?
Things get a bit... delicate wrapping memcmp/memcpy/memmove/memset like
this. These functions are basically primitives in C, and the compiler
can get up to all sort of tricks eliding/folding these. Unfortunately,
even just wrapping these in static inline functions seems to create
problems, so I've just defaulted to #defining the relevant lfs_*
symbols.
Even weirder, GCC's __builtin_* variants seem to be worse, code-wise,
than the stdlib symbols. Maybe because these ignore -Os hints? For this
reason I've prioritized the string.h's symbols unless LFS_NO_STRINGH is
defined:
code stack
before: 33338 2640
static-inline: 33422 (+0.3%) 2648 (+0.3%)
builtins: 33402 (+0.2%) 2640 (+0.0%)
after: 33342 (+0.0%) 2640 (+0.0%)
Comparing the LFS_NO_STRINGH and LFS_NO_INTRINSICS builds, just for
curiosity:
code stack
default: 33342 2640
no-string.h: 33486 (+0.4%) 2640 (+0.0%)
no-intrinsics: 33514 (+0.5%) 2616 (-0.9%)
no-both: 33722 (+1.1%) 2624 (-0.6%)
The extra 4 bytes introduced seem to come from the added
lfs_gdelta_xor -> lfs_memxor indirection, not really sure why, maybe
compiler/instruction alignment noise?
Why not provide __builtin_* variants for all string.h symbols? To be
honest, because we really don't care about the performance of strlen/
strcpy/strspn in littlefs. And in environments where string.h is not
available it's likely __builtin_str* won't be as well.
Note the test/bench frameworks should stick with the stdlib symbols. By
default C code should assume these are always available, and this makes
it slightly more reliable to test with -DLFS_NO_STRINGH or
-DLFS_NO_INTRINSICS.
This commit is contained in:
@@ -125,7 +125,7 @@ static int lfsr_bd_read_(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
||||
lfs_size_t size_ = lfs_min(
|
||||
size - (off_-off),
|
||||
lfs->pcache.size - (off_-lfs->pcache.off));
|
||||
memcpy(&buffer_[off_-off],
|
||||
lfs_memcpy(&buffer_[off_-off],
|
||||
&lfs->pcache.buffer[off_-lfs->pcache.off],
|
||||
size_);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ static int lfsr_bd_prog_(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
||||
lfs_size_t size_ = lfs_min(
|
||||
size - (off_-off),
|
||||
lfs->rcache.size - (off_-lfs->rcache.off));
|
||||
memcpy(&lfs->rcache.buffer[off_-lfs->rcache.off],
|
||||
lfs_memcpy(&lfs->rcache.buffer[off_-lfs->rcache.off],
|
||||
&buffer_[off_-off],
|
||||
size_);
|
||||
}
|
||||
@@ -275,7 +275,7 @@ static int lfsr_bd_read(lfs_t *lfs,
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(buffer_, buffer__, size__);
|
||||
lfs_memcpy(buffer_, buffer__, size__);
|
||||
|
||||
off_ += size__;
|
||||
hint_ -= size__;
|
||||
@@ -295,7 +295,7 @@ static int lfsr_bd_flush(lfs_t *lfs, uint32_t *cksum_) {
|
||||
lfs_size_t aligned_size = lfs_alignup(
|
||||
lfs->pcache.size,
|
||||
lfs->cfg->prog_size);
|
||||
memset(&lfs->pcache.buffer[lfs->pcache.size],
|
||||
lfs_memset(&lfs->pcache.buffer[lfs->pcache.size],
|
||||
0xff,
|
||||
aligned_size - lfs->pcache.size);
|
||||
|
||||
@@ -341,7 +341,7 @@ static int lfsr_bd_prognext(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
||||
}
|
||||
|
||||
// zero to avoid any information leaks
|
||||
memset(&lfs->pcache.buffer[lfs->pcache.size],
|
||||
lfs_memset(&lfs->pcache.buffer[lfs->pcache.size],
|
||||
0xff,
|
||||
(off-lfs->pcache.off) - lfs->pcache.size);
|
||||
lfs->pcache.size = lfs_max(
|
||||
@@ -411,7 +411,7 @@ static int lfsr_bd_prog(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
||||
return err;
|
||||
}
|
||||
|
||||
memcpy(buffer__, buffer_, size__);
|
||||
lfs_memcpy(buffer__, buffer_, size__);
|
||||
|
||||
off_ += size__;
|
||||
buffer_ += size__;
|
||||
@@ -531,7 +531,7 @@ static lfs_scmp_t lfsr_bd_cmp(lfs_t *lfs,
|
||||
return err;
|
||||
}
|
||||
|
||||
int res = memcmp(buffer__, buffer_, size__);
|
||||
int res = lfs_memcmp(buffer__, buffer_, size__);
|
||||
if (res != 0) {
|
||||
return (res < 0) ? LFS_CMP_LT : LFS_CMP_GT;
|
||||
}
|
||||
@@ -604,7 +604,7 @@ static int lfsr_bd_set(lfs_t *lfs, lfs_block_t block, lfs_size_t off,
|
||||
return err;
|
||||
}
|
||||
|
||||
memset(buffer__, c, size__);
|
||||
lfs_memset(buffer__, c, size__);
|
||||
|
||||
// optional checksum
|
||||
if (cksum_) {
|
||||
@@ -1263,7 +1263,7 @@ static lfs_ssize_t lfsr_data_read(lfs_t *lfs, lfsr_data_t *data,
|
||||
|
||||
// buffer?
|
||||
} else {
|
||||
memcpy(buffer, data->u.buffer, d);
|
||||
lfs_memcpy(buffer, data->u.buffer, d);
|
||||
}
|
||||
|
||||
*data = lfsr_data_slice(*data, d, -1);
|
||||
@@ -1348,7 +1348,7 @@ static lfs_scmp_t lfsr_data_cmp(lfs_t *lfs, lfsr_data_t data,
|
||||
|
||||
// buffer?
|
||||
} else {
|
||||
int cmp = memcmp(data.u.buffer, buffer, d);
|
||||
int cmp = lfs_memcmp(data.u.buffer, buffer, d);
|
||||
if (cmp < 0) {
|
||||
return LFS_CMP_LT;
|
||||
} else if (cmp > 0) {
|
||||
@@ -2621,7 +2621,7 @@ static inline int lfsr_rbyd_p_push(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
return err;
|
||||
}
|
||||
|
||||
memmove(p+1, p, 2*sizeof(lfsr_alt_t));
|
||||
lfs_memmove(p+1, p, 2*sizeof(lfsr_alt_t));
|
||||
p[0].alt = alt;
|
||||
p[0].weight = weight;
|
||||
p[0].jump = jump;
|
||||
@@ -2630,7 +2630,7 @@ static inline int lfsr_rbyd_p_push(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
|
||||
static inline void lfsr_rbyd_p_pop(
|
||||
lfsr_alt_t p[static 3]) {
|
||||
memmove(p, p+1, 2*sizeof(lfsr_alt_t));
|
||||
lfs_memmove(p, p+1, 2*sizeof(lfsr_alt_t));
|
||||
p[2].alt = 0;
|
||||
}
|
||||
|
||||
@@ -5344,13 +5344,7 @@ static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||
|
||||
static inline bool lfsr_gdelta_iszero(
|
||||
const uint8_t *gdelta, lfs_size_t size) {
|
||||
for (lfs_size_t i = 0; i < size; i++) {
|
||||
if (gdelta[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return lfs_memcchr(gdelta, 0, size) == NULL;
|
||||
}
|
||||
|
||||
static inline lfs_size_t lfsr_gdelta_size(
|
||||
@@ -5363,13 +5357,9 @@ static inline lfs_size_t lfsr_gdelta_size(
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline uint8_t *lfsr_gdelta_xor(
|
||||
static inline void lfsr_gdelta_xor(
|
||||
uint8_t *a, const uint8_t *b, lfs_size_t size) {
|
||||
for (lfs_size_t i = 0; i < size; i++) {
|
||||
a[i] ^= b[i];
|
||||
}
|
||||
|
||||
return a;
|
||||
lfs_memxor(a, b, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -5407,7 +5397,7 @@ static inline bool lfsr_grm_ispending(const lfsr_grm_t *grm,
|
||||
static lfsr_data_t lfsr_data_fromgrm(const lfsr_grm_t *grm,
|
||||
uint8_t buffer[static LFSR_GRM_DSIZE]) {
|
||||
// make sure to zero so we don't leak any info
|
||||
memset(buffer, 0, LFSR_GRM_DSIZE);
|
||||
lfs_memset(buffer, 0, LFSR_GRM_DSIZE);
|
||||
|
||||
// first encode the number of grms, this can be 0, 1, or 2 and may
|
||||
// be extended to a general purpose leb128 type field in the future
|
||||
@@ -5462,7 +5452,7 @@ static int lfsr_data_readgrm(lfs_t *lfs, lfsr_data_t *data,
|
||||
|
||||
// some mdir-related gstate things we need
|
||||
static void lfsr_fs_flushgdelta(lfs_t *lfs) {
|
||||
memset(lfs->grm_d, 0, LFSR_GRM_DSIZE);
|
||||
lfs_memset(lfs->grm_d, 0, LFSR_GRM_DSIZE);
|
||||
}
|
||||
|
||||
static void lfsr_fs_preparegdelta(lfs_t *lfs) {
|
||||
@@ -5502,7 +5492,7 @@ static int lfsr_rbyd_appendgdelta(lfs_t *lfs, lfsr_rbyd_t *rbyd) {
|
||||
}
|
||||
|
||||
uint8_t grm_d[LFSR_GRM_DSIZE];
|
||||
memset(grm_d, 0, LFSR_GRM_DSIZE);
|
||||
lfs_memset(grm_d, 0, LFSR_GRM_DSIZE);
|
||||
if (err != LFS_ERR_NOENT) {
|
||||
lfs_ssize_t d = lfsr_data_read(lfs, &data, grm_d, LFSR_GRM_DSIZE);
|
||||
if (d < 0) {
|
||||
@@ -7289,12 +7279,12 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const lfsr_mtree_t *mtree,
|
||||
lfs_size_t name_size = 0;
|
||||
while (true) {
|
||||
// skip slashes
|
||||
path += strspn(path, "/");
|
||||
lfs_size_t name_size__ = strcspn(path, "/");
|
||||
path += lfs_strspn(path, "/");
|
||||
lfs_size_t name_size__ = lfs_strcspn(path, "/");
|
||||
|
||||
// skip '.' and root '..'
|
||||
if ((name_size__ == 1 && memcmp(path, ".", 1) == 0)
|
||||
|| (name_size__ == 2 && memcmp(path, "..", 2) == 0)) {
|
||||
if ((name_size__ == 1 && lfs_memcmp(path, ".", 1) == 0)
|
||||
|| (name_size__ == 2 && lfs_memcmp(path, "..", 2) == 0)) {
|
||||
path += name_size__;
|
||||
goto next;
|
||||
}
|
||||
@@ -7304,13 +7294,13 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const lfsr_mtree_t *mtree,
|
||||
lfs_size_t suffix_size;
|
||||
int depth = 1;
|
||||
while (true) {
|
||||
suffix += strspn(suffix, "/");
|
||||
suffix_size = strcspn(suffix, "/");
|
||||
suffix += lfs_strspn(suffix, "/");
|
||||
suffix_size = lfs_strcspn(suffix, "/");
|
||||
if (suffix_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (suffix_size == 2 && memcmp(suffix, "..", 2) == 0) {
|
||||
if (suffix_size == 2 && lfs_memcmp(suffix, "..", 2) == 0) {
|
||||
depth -= 1;
|
||||
if (depth == 0) {
|
||||
path = suffix + suffix_size;
|
||||
@@ -7379,7 +7369,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const lfsr_mtree_t *mtree,
|
||||
&mdir, &tag, NULL);
|
||||
if (err) {
|
||||
// report where to insert if we are the last name in our path
|
||||
if (err == LFS_ERR_NOENT && strchr(name, '/') == NULL) {
|
||||
if (err == LFS_ERR_NOENT && lfs_strchr(name, '/') == NULL) {
|
||||
if (mdir_) {
|
||||
*mdir_ = mdir;
|
||||
}
|
||||
@@ -8404,7 +8394,7 @@ static int lfsr_mountinited(lfs_t *lfs) {
|
||||
|
||||
// TODO should the consumegdelta above take gstate/gdelta as a parameter?
|
||||
// keep track of the current gstate on disk
|
||||
memcpy(lfs->grm_p, lfs->grm_d, LFSR_GRM_DSIZE);
|
||||
lfs_memcpy(lfs->grm_p, lfs->grm_d, LFSR_GRM_DSIZE);
|
||||
|
||||
// decode grm so we can report any removed files as missing
|
||||
int err = lfsr_data_readgrm(lfs,
|
||||
@@ -8636,7 +8626,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block, bool erase) {
|
||||
lfs->lookahead.size = lfs_min32(
|
||||
8*lfs->cfg->lookahead_size,
|
||||
lfs->lookahead.ckpoint);
|
||||
memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);
|
||||
lfs_memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);
|
||||
|
||||
// traverse the filesystem, building up knowledge of what blocks are
|
||||
// in use in our lookahead window
|
||||
@@ -8942,7 +8932,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) {
|
||||
lfs_nlog2(lfsr_mtree_weight(&lfs->mtree))
|
||||
+ lfs_nlog2(lfs->cfg->block_size/32),
|
||||
31)) - 1;
|
||||
lfsr_did_t did_ = lfs_crc32c(0, path, strlen(path)) & dmask;
|
||||
lfsr_did_t did_ = lfs_crc32c(0, path, lfs_strlen(path)) & dmask;
|
||||
|
||||
// Check if we have a collision. If we do, search for the next
|
||||
// available did
|
||||
@@ -9387,7 +9377,7 @@ int lfsr_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
|
||||
// special case for root
|
||||
if (err == LFS_ERR_INVAL) {
|
||||
strcpy(info->name, "/");
|
||||
lfs_strcpy(info->name, "/");
|
||||
info->type = LFS_TYPE_DIR;
|
||||
info->size = 0;
|
||||
return 0;
|
||||
@@ -9466,13 +9456,13 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info) {
|
||||
|
||||
// handle dots specially
|
||||
if (dir->pos == 0) {
|
||||
strcpy(info->name, ".");
|
||||
lfs_strcpy(info->name, ".");
|
||||
info->type = LFS_TYPE_DIR;
|
||||
info->size = 0;
|
||||
dir->pos += 1;
|
||||
return 0;
|
||||
} else if (dir->pos == 1) {
|
||||
strcpy(info->name, "..");
|
||||
lfs_strcpy(info->name, "..");
|
||||
info->type = LFS_TYPE_DIR;
|
||||
info->size = 0;
|
||||
dir->pos += 1;
|
||||
@@ -10199,7 +10189,7 @@ static lfs_ssize_t lfsr_bshrub_readnext(lfs_t *lfs, const lfsr_file_t *file,
|
||||
|
||||
// found a hole? fill with zeros
|
||||
lfs_ssize_t d = lfs_min32(size, bid+1 - pos_);
|
||||
memset(buffer, 0, d);
|
||||
lfs_memset(buffer, 0, d);
|
||||
|
||||
pos_ += d;
|
||||
buffer += d;
|
||||
@@ -11146,7 +11136,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
||||
lfs_ssize_t d_ = lfs_min32(
|
||||
d,
|
||||
file->buffer.size - (pos_ - file->buffer.pos));
|
||||
memcpy(buffer_,
|
||||
lfs_memcpy(buffer_,
|
||||
&file->buffer.buffer[pos_ - file->buffer.pos],
|
||||
d_);
|
||||
|
||||
@@ -11205,7 +11195,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
||||
}
|
||||
|
||||
// found a hole? fill with zeros
|
||||
memset(buffer_, 0, d);
|
||||
lfs_memset(buffer_, 0, d);
|
||||
|
||||
pos_ += d;
|
||||
buffer_ += d;
|
||||
@@ -11251,7 +11241,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
&& pos <= lfsr_file_inlinesize(lfs, file)) {
|
||||
LFS_ASSERT(lfsr_f_isunflush(file->o.flags));
|
||||
LFS_ASSERT(lfsr_file_size_(file) == file->buffer.size);
|
||||
memset(&file->buffer.buffer[file->buffer.size],
|
||||
lfs_memset(&file->buffer.buffer[file->buffer.size],
|
||||
0,
|
||||
pos - file->buffer.size);
|
||||
file->buffer.size = pos;
|
||||
@@ -11279,7 +11269,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
// note we need to clear the buffer anyways to avoid any
|
||||
// out-of-date data
|
||||
file->buffer.pos = pos + size - lfsr_file_buffersize(lfs, file);
|
||||
memcpy(file->buffer.buffer,
|
||||
lfs_memcpy(file->buffer.buffer,
|
||||
&buffer_[size - lfsr_file_buffersize(lfs, file)],
|
||||
lfsr_file_buffersize(lfs, file));
|
||||
file->buffer.size = lfsr_file_buffersize(lfs, file);
|
||||
@@ -11317,7 +11307,9 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file,
|
||||
size,
|
||||
lfsr_file_buffersize(lfs, file)
|
||||
- (pos - file->buffer.pos));
|
||||
memcpy(&file->buffer.buffer[pos - file->buffer.pos], buffer_, d);
|
||||
lfs_memcpy(&file->buffer.buffer[pos - file->buffer.pos],
|
||||
buffer_,
|
||||
d);
|
||||
file->buffer.size = lfs_max32(
|
||||
file->buffer.size,
|
||||
pos+d - file->buffer.pos);
|
||||
@@ -11556,7 +11548,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
|
||||
file_->buffer.pos = file->buffer.pos;
|
||||
LFS_ASSERT(file->buffer.size
|
||||
<= lfsr_file_buffersize(lfs, file));
|
||||
memcpy(file_->buffer.buffer,
|
||||
lfs_memcpy(file_->buffer.buffer,
|
||||
file->buffer.buffer,
|
||||
file->buffer.size);
|
||||
file_->buffer.size = file->buffer.size;
|
||||
@@ -11664,7 +11656,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
|
||||
// we may need to zero some of our buffer
|
||||
if (size_ > file->buffer.size) {
|
||||
memset(&file->buffer.buffer[file->buffer.size],
|
||||
lfs_memset(&file->buffer.buffer[file->buffer.size],
|
||||
0,
|
||||
size_ - file->buffer.size);
|
||||
}
|
||||
@@ -11771,16 +11763,16 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
|
||||
// we may need to move the data in our buffer
|
||||
if (file->buffer.size > size_) {
|
||||
memmove(file->buffer.buffer,
|
||||
lfs_memmove(file->buffer.buffer,
|
||||
&file->buffer.buffer[file->buffer.size - size_],
|
||||
file->buffer.size);
|
||||
}
|
||||
// we may need to zero some of our buffer
|
||||
if (size_ > file->buffer.size) {
|
||||
memmove(&file->buffer.buffer[size_ - file->buffer.size],
|
||||
lfs_memmove(&file->buffer.buffer[size_ - file->buffer.size],
|
||||
file->buffer.buffer,
|
||||
file->buffer.size);
|
||||
memset(file->buffer.buffer,
|
||||
lfs_memset(file->buffer.buffer,
|
||||
0,
|
||||
size_ - file->buffer.size);
|
||||
}
|
||||
@@ -11804,7 +11796,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
||||
}
|
||||
|
||||
// fruncate our buffer
|
||||
memmove(file->buffer.buffer,
|
||||
lfs_memmove(file->buffer.buffer,
|
||||
&file->buffer.buffer[lfs_min32(
|
||||
lfs_smax32(
|
||||
size - size_ - file->buffer.pos,
|
||||
@@ -15422,8 +15414,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
lfs->opened = NULL;
|
||||
|
||||
// zero gstate
|
||||
memset(lfs->grm_p, 0, LFSR_GRM_DSIZE);
|
||||
memset(lfs->grm_d, 0, LFSR_GRM_DSIZE);
|
||||
lfs_memset(lfs->grm_p, 0, LFSR_GRM_DSIZE);
|
||||
lfs_memset(lfs->grm_d, 0, LFSR_GRM_DSIZE);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
+246
-8
@@ -24,9 +24,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef LFS_NO_STRINGH
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifndef LFS_NO_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -362,6 +363,243 @@ ssize_t lfs_toleb128(uint32_t word, void *buffer, size_t size);
|
||||
ssize_t lfs_fromleb128(uint32_t *word, const void *buffer, size_t size);
|
||||
|
||||
|
||||
// Compare n bytes of memory
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_memcmp memcmp
|
||||
#elif !defined(LFS_NO_INTRINSICS)
|
||||
#define lfs_memcmp __builtin_memcmp
|
||||
#else
|
||||
static inline int lfs_memcmp(const void *a, const void *b, size_t size) {
|
||||
const uint8_t *a_ = a;
|
||||
const uint8_t *b_ = b;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (a_[i] != b_[i]) {
|
||||
return (int)a_[i] - (int)b_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy n bytes from src to dst, src and dst must not overlap
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_memcpy memcpy
|
||||
#elif !defined(LFS_NO_INTRINSICS)
|
||||
#define lfs_memcpy __builtin_memcpy
|
||||
#else
|
||||
static inline void *lfs_memcpy(
|
||||
void *restrict dst, const void *restrict src, size_t size) {
|
||||
uint8_t *dst_ = dst;
|
||||
const uint8_t *src_ = src;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
dst_[i] = src_[i];
|
||||
}
|
||||
|
||||
return dst_;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy n bytes from src to dst, src and dst may overlap
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_memmove memmove
|
||||
#elif !defined(LFS_NO_INTRINSICS)
|
||||
#define lfs_memmove __builtin_memmove
|
||||
#else
|
||||
static inline void *lfs_memmove(void *dst, const void *src, size_t size) {
|
||||
uint8_t *dst_ = dst;
|
||||
const uint8_t *src_ = src;
|
||||
if (dst_ < src_) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
dst_[i] = src_[i];
|
||||
}
|
||||
} else if (dst_ > src_) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
dst_[(size-1)-i] = src_[(size-1)-i];
|
||||
}
|
||||
}
|
||||
|
||||
return dst_;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set n bytes to c
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_memset memset
|
||||
#elif !defined(LFS_NO_INTRINSICS)
|
||||
#define lfs_memset __builtin_memset
|
||||
#else
|
||||
static inline void *lfs_memset(void *dst, int c, size_t size) {
|
||||
uint8_t *dst_ = dst;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
dst_[i] = c;
|
||||
}
|
||||
|
||||
return dst_;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the first occurrence of c or NULL
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_memchr memchr
|
||||
#else
|
||||
static inline void *lfs_memchr(const void *a, int c, size_t size) {
|
||||
const uint8_t *a_ = a;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (a_[i] == c) {
|
||||
return (void*)&a_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the first occurrence of anything not c or NULL
|
||||
static inline void *lfs_memcchr(const void *a, int c, size_t size) {
|
||||
const uint8_t *a_ = a;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (a_[i] != c) {
|
||||
return (void*)&a_[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Xor n bytes from b into a
|
||||
static inline void *lfs_memxor(
|
||||
void *restrict a, const void *restrict b, size_t size) {
|
||||
uint8_t *a_ = a;
|
||||
const uint8_t *b_ = b;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
a_[i] ^= b_[i];
|
||||
}
|
||||
|
||||
return a_;
|
||||
}
|
||||
|
||||
|
||||
// Find the length of a null-terminated string
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_strlen strlen
|
||||
#else
|
||||
static inline size_t lfs_strlen(const char *a) {
|
||||
const char *a_ = a;
|
||||
while (*a_) {
|
||||
a_++;
|
||||
}
|
||||
|
||||
return a_ - a;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compare two null-terminated strings
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_strcmp strcmp
|
||||
#else
|
||||
static inline int lfs_strcmp(const char *a, const char *b) {
|
||||
while (*a && *a == *b) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return (int)*a - (int)*b;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy a null-terminated string from src to dst
|
||||
#if !defined(LFS_NO_STRINGH)
|
||||
#define lfs_strcpy strcpy
|
||||
#else
|
||||
static inline char *lfs_strcpy(
|
||||
char *restrict dst, const char *restrict src) {
|
||||
char *dst_ = dst;
|
||||
while (*src) {
|
||||
*dst_ = *src;
|
||||
dst_++;
|
||||
src++;
|
||||
}
|
||||
|
||||
*dst_ = '\0';
|
||||
return dst;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find first occurrence of c or NULL
|
||||
#ifndef LFS_NO_STRINGH
|
||||
#define lfs_strchr strchr
|
||||
#else
|
||||
static inline char *lfs_strchr(const char *a, int c) {
|
||||
while (*a) {
|
||||
if (*a == c) {
|
||||
return (char*)a;
|
||||
}
|
||||
|
||||
a++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find first occurrence of anything not c or NULL
|
||||
static inline char *lfs_strcchr(const char *a, int c) {
|
||||
while (*a) {
|
||||
if (*a != c) {
|
||||
return (char*)a;
|
||||
}
|
||||
|
||||
a++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find length of a that does not contain any char in cs
|
||||
#ifndef LFS_NO_STRINGH
|
||||
#define lfs_strspn strspn
|
||||
#else
|
||||
static inline size_t lfs_strspn(const char *a, const char *cs) {
|
||||
const char *a_ = a;
|
||||
while (*a_) {
|
||||
const char *cs_ = cs;
|
||||
while (*cs_) {
|
||||
if (*a_ != *cs_) {
|
||||
return a_ - a;
|
||||
}
|
||||
cs_++;
|
||||
}
|
||||
|
||||
a_++;
|
||||
}
|
||||
|
||||
return a_ - a;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find length of a that only contains chars in cs
|
||||
#ifndef LFS_NO_STRINGH
|
||||
#define lfs_strcspn strcspn
|
||||
#else
|
||||
static inline size_t lfs_strcspn(const char *a, const char *cs) {
|
||||
const char *a_ = a;
|
||||
while (*a_) {
|
||||
const char *cs_ = cs;
|
||||
while (*cs_) {
|
||||
if (*a_ == *cs_) {
|
||||
return a_ - a;
|
||||
}
|
||||
cs_++;
|
||||
}
|
||||
|
||||
a_++;
|
||||
}
|
||||
|
||||
return a_ - a;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||
//uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
|
||||
@@ -377,23 +615,23 @@ uint32_t lfs_crc32c(uint32_t crc, const void *buffer, size_t size);
|
||||
|
||||
// Allocate memory, only used if buffers are not provided to littlefs
|
||||
// Note, memory must be 64-bit aligned
|
||||
static inline void *lfs_malloc(size_t size) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
return malloc(size);
|
||||
#define lfs_malloc malloc
|
||||
#else
|
||||
static inline void *lfs_malloc(size_t size) {
|
||||
(void)size;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void lfs_free(void *p) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
free(p);
|
||||
#define lfs_free free
|
||||
#else
|
||||
static inline void lfs_free(void *p) {
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user