mirror of
https://github.com/No-Chicken/Power-Pico.git
synced 2026-04-03 13:02:36 +08:00
移动文件夹
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* @file lv_malloc_core.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_mem.h"
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN
|
||||
|
||||
#include "lv_tlsf.h"
|
||||
#include "../lv_string.h"
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../misc/lv_log.h"
|
||||
#include "../../misc/lv_ll.h"
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../osal/lv_os.h"
|
||||
#include "../../core/lv_global.h"
|
||||
|
||||
#ifdef LV_MEM_POOL_INCLUDE
|
||||
#include LV_MEM_POOL_INCLUDE
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/
|
||||
#ifndef LV_MEM_ADD_JUNK
|
||||
#define LV_MEM_ADD_JUNK 0
|
||||
#endif
|
||||
|
||||
#ifdef LV_ARCH_64
|
||||
#define MEM_UNIT uint64_t
|
||||
#define ALIGN_MASK 0x7
|
||||
#else
|
||||
#define MEM_UNIT uint32_t
|
||||
#define ALIGN_MASK 0x3
|
||||
#endif
|
||||
#define state LV_GLOBAL_DEFAULT()->tlsf_state
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static void lv_mem_walker(void * ptr, size_t size, int used, void * user);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_MEM
|
||||
#define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define LV_TRACE_MEM(...)
|
||||
#endif
|
||||
|
||||
#define _COPY(d, s) *d = *s; d++; s++;
|
||||
#define _SET(d, v) *d = v; d++;
|
||||
#define _REPEAT8(expr) expr expr expr expr expr expr expr expr
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_init(&state.mutex);
|
||||
#endif
|
||||
|
||||
#if LV_MEM_ADR == 0
|
||||
#ifdef LV_MEM_POOL_ALLOC
|
||||
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_POOL_ALLOC(LV_MEM_SIZE), LV_MEM_SIZE);
|
||||
#else
|
||||
/*Allocate a large array to store the dynamically allocated data*/
|
||||
static LV_ATTRIBUTE_LARGE_RAM_ARRAY MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)];
|
||||
state.tlsf = lv_tlsf_create_with_pool((void *)work_mem_int, LV_MEM_SIZE);
|
||||
#endif
|
||||
#else
|
||||
state.tlsf = lv_tlsf_create_with_pool((void *)LV_MEM_ADR, LV_MEM_SIZE);
|
||||
#endif
|
||||
|
||||
lv_ll_init(&state.pool_ll, sizeof(lv_pool_t));
|
||||
|
||||
/*Record the first pool*/
|
||||
lv_pool_t * pool_p = lv_ll_ins_tail(&state.pool_ll);
|
||||
LV_ASSERT_MALLOC(pool_p);
|
||||
*pool_p = lv_tlsf_get_pool(state.tlsf);
|
||||
|
||||
#if LV_MEM_ADD_JUNK
|
||||
LV_LOG_WARN("LV_MEM_ADD_JUNK is enabled which makes LVGL much slower");
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_mem_deinit(void)
|
||||
{
|
||||
lv_ll_clear(&state.pool_ll);
|
||||
lv_tlsf_destroy(state.tlsf);
|
||||
#if LV_USE_OS
|
||||
lv_mutex_delete(&state.mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes)
|
||||
{
|
||||
lv_mem_pool_t new_pool = lv_tlsf_add_pool(state.tlsf, mem, bytes);
|
||||
if(!new_pool) {
|
||||
LV_LOG_WARN("failed to add memory pool, address: %p, size: %zu", mem, bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_pool_t * pool_p = lv_ll_ins_tail(&state.pool_ll);
|
||||
LV_ASSERT_MALLOC(pool_p);
|
||||
*pool_p = new_pool;
|
||||
|
||||
return new_pool;
|
||||
}
|
||||
|
||||
void lv_mem_remove_pool(lv_mem_pool_t pool)
|
||||
{
|
||||
lv_pool_t * pool_p;
|
||||
LV_LL_READ(&state.pool_ll, pool_p) {
|
||||
if(*pool_p == pool) {
|
||||
lv_ll_remove(&state.pool_ll, pool_p);
|
||||
lv_free(pool_p);
|
||||
lv_tlsf_remove_pool(state.tlsf, pool);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LV_LOG_WARN("invalid pool: %p", pool);
|
||||
}
|
||||
|
||||
void * lv_malloc_core(size_t size)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_lock(&state.mutex);
|
||||
#endif
|
||||
void * p = lv_tlsf_malloc(state.tlsf, size);
|
||||
|
||||
if(p) {
|
||||
state.cur_used += lv_tlsf_block_size(p);
|
||||
state.max_used = LV_MAX(state.cur_used, state.max_used);
|
||||
}
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
void * lv_realloc_core(void * p, size_t new_size)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_lock(&state.mutex);
|
||||
#endif
|
||||
|
||||
size_t old_size = lv_tlsf_block_size(p);
|
||||
void * p_new = lv_tlsf_realloc(state.tlsf, p, new_size);
|
||||
|
||||
if(p_new) {
|
||||
state.cur_used -= old_size;
|
||||
state.cur_used += lv_tlsf_block_size(p_new);
|
||||
state.max_used = LV_MAX(state.cur_used, state.max_used);
|
||||
}
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
|
||||
return p_new;
|
||||
}
|
||||
|
||||
void lv_free_core(void * p)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_lock(&state.mutex);
|
||||
#endif
|
||||
|
||||
#if LV_MEM_ADD_JUNK
|
||||
lv_memset(p, 0xbb, lv_tlsf_block_size(data));
|
||||
#endif
|
||||
size_t size = lv_tlsf_block_size(p);
|
||||
lv_tlsf_free(state.tlsf, p);
|
||||
if(state.cur_used > size) state.cur_used -= size;
|
||||
else state.cur_used = 0;
|
||||
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
/*Init the data*/
|
||||
lv_memzero(mon_p, sizeof(lv_mem_monitor_t));
|
||||
LV_TRACE_MEM("begin");
|
||||
|
||||
lv_pool_t * pool_p;
|
||||
LV_LL_READ(&state.pool_ll, pool_p) {
|
||||
lv_tlsf_walk_pool(*pool_p, lv_mem_walker, mon_p);
|
||||
}
|
||||
|
||||
mon_p->used_pct = 100 - (uint64_t)100U * mon_p->free_size / mon_p->total_size;
|
||||
if(mon_p->free_size > 0) {
|
||||
mon_p->frag_pct = (uint64_t)mon_p->free_biggest_size * 100U / mon_p->free_size;
|
||||
mon_p->frag_pct = 100 - mon_p->frag_pct;
|
||||
}
|
||||
else {
|
||||
mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/
|
||||
}
|
||||
|
||||
mon_p->max_used = state.max_used;
|
||||
|
||||
LV_TRACE_MEM("finished");
|
||||
}
|
||||
|
||||
lv_result_t lv_mem_test_core(void)
|
||||
{
|
||||
#if LV_USE_OS
|
||||
lv_mutex_lock(&state.mutex);
|
||||
#endif
|
||||
if(lv_tlsf_check(state.tlsf)) {
|
||||
LV_LOG_WARN("failed");
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_pool_t * pool_p;
|
||||
LV_LL_READ(&state.pool_ll, pool_p) {
|
||||
if(lv_tlsf_check_pool(*pool_p)) {
|
||||
LV_LOG_WARN("pool failed");
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
LV_TRACE_MEM("passed");
|
||||
#if LV_USE_OS
|
||||
lv_mutex_unlock(&state.mutex);
|
||||
#endif
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_mem_walker(void * ptr, size_t size, int used, void * user)
|
||||
{
|
||||
LV_UNUSED(ptr);
|
||||
|
||||
lv_mem_monitor_t * mon_p = user;
|
||||
mon_p->total_size += size;
|
||||
if(used) {
|
||||
mon_p->used_cnt++;
|
||||
}
|
||||
else {
|
||||
mon_p->free_cnt++;
|
||||
mon_p->free_size += size;
|
||||
if(size > mon_p->free_biggest_size)
|
||||
mon_p->free_biggest_size = size;
|
||||
}
|
||||
}
|
||||
#endif /*LV_STDLIB_BUILTIN*/
|
||||
@@ -0,0 +1,886 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// \author (c) Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
//
|
||||
// \license The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
|
||||
// embedded systems with a very limited resources. These routines are thread
|
||||
// safe and reentrant!
|
||||
// Use this instead of the bloated standard/newlib printf cause these use
|
||||
// malloc for printf (and may not be thread safe).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*Original repository: https://github.com/mpaland/printf*/
|
||||
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_BUILTIN
|
||||
|
||||
#include "../lv_sprintf.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
|
||||
#define PRINTF_DISABLE_SUPPORT_FLOAT (!LV_USE_FLOAT)
|
||||
|
||||
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
|
||||
// numeric number including padded zeros (dynamically created on stack)
|
||||
// default: 32 byte
|
||||
#ifndef PRINTF_NTOA_BUFFER_SIZE
|
||||
#define PRINTF_NTOA_BUFFER_SIZE 32U
|
||||
#endif
|
||||
|
||||
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
|
||||
// float number including padded zeros (dynamically created on stack)
|
||||
// default: 32 byte
|
||||
#ifndef PRINTF_FTOA_BUFFER_SIZE
|
||||
#define PRINTF_FTOA_BUFFER_SIZE 32U
|
||||
#endif
|
||||
|
||||
// support for the floating point type (%f)
|
||||
// default: activated
|
||||
#if !PRINTF_DISABLE_SUPPORT_FLOAT
|
||||
#define PRINTF_SUPPORT_FLOAT
|
||||
#endif
|
||||
|
||||
// support for exponential floating point notation (%e/%g)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
|
||||
#define PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif
|
||||
|
||||
// define the default floating point precision
|
||||
// default: 6 digits
|
||||
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
|
||||
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
|
||||
#endif
|
||||
|
||||
// define the largest float suitable to print with %f
|
||||
// default: 1e9
|
||||
#ifndef PRINTF_MAX_FLOAT
|
||||
#define PRINTF_MAX_FLOAT 1e9
|
||||
#endif
|
||||
|
||||
// support for the long long types (%llu or %p)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
|
||||
#define PRINTF_SUPPORT_LONG_LONG
|
||||
#endif
|
||||
|
||||
// support for the ptrdiff_t type (%t)
|
||||
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
|
||||
#define PRINTF_SUPPORT_PTRDIFF_T
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// internal flag definitions
|
||||
#define FLAGS_ZEROPAD (1U << 0U)
|
||||
#define FLAGS_LEFT (1U << 1U)
|
||||
#define FLAGS_PLUS (1U << 2U)
|
||||
#define FLAGS_SPACE (1U << 3U)
|
||||
#define FLAGS_HASH (1U << 4U)
|
||||
#define FLAGS_UPPERCASE (1U << 5U)
|
||||
#define FLAGS_CHAR (1U << 6U)
|
||||
#define FLAGS_SHORT (1U << 7U)
|
||||
#define FLAGS_LONG (1U << 8U)
|
||||
#define FLAGS_LONG_LONG (1U << 9U)
|
||||
#define FLAGS_PRECISION (1U << 10U)
|
||||
#define FLAGS_ADAPT_EXP (1U << 11U)
|
||||
|
||||
typedef struct {
|
||||
const char * fmt;
|
||||
va_list * va;
|
||||
} lv_vaformat_t;
|
||||
|
||||
// import float.h for DBL_MAX
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
// output function type
|
||||
typedef void (*out_fct_type)(char character, void * buffer, size_t idx, size_t maxlen);
|
||||
|
||||
// wrapper (used as buffer) for output function type
|
||||
typedef struct {
|
||||
void (*fct)(char character, void * arg);
|
||||
void * arg;
|
||||
} out_fct_wrap_type;
|
||||
|
||||
// internal buffer output
|
||||
static inline void _out_buffer(char character, void * buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
if(idx < maxlen) {
|
||||
((char *)buffer)[idx] = character;
|
||||
}
|
||||
}
|
||||
|
||||
// internal null output
|
||||
static inline void _out_null(char character, void * buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
LV_UNUSED(character);
|
||||
LV_UNUSED(buffer);
|
||||
LV_UNUSED(idx);
|
||||
LV_UNUSED(maxlen);
|
||||
}
|
||||
|
||||
// internal secure strlen
|
||||
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
|
||||
static inline unsigned int _strnlen_s(const char * str, size_t maxsize)
|
||||
{
|
||||
const char * s;
|
||||
for(s = str; *s && maxsize--; ++s);
|
||||
return (unsigned int)(s - str);
|
||||
}
|
||||
|
||||
// internal test if char is a digit (0-9)
|
||||
// \return true if char is a digit
|
||||
static inline bool _is_digit(char ch)
|
||||
{
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
// internal ASCII string to unsigned int conversion
|
||||
static unsigned int _atoi(const char ** str)
|
||||
{
|
||||
unsigned int i = 0U;
|
||||
while(_is_digit(**str)) {
|
||||
i = i * 10U + (unsigned int)(*((*str)++) - '0');
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// output the specified string in reverse, taking care of any zero-padding
|
||||
static size_t _out_rev(out_fct_type out, char * buffer, size_t idx, size_t maxlen, const char * buf, size_t len,
|
||||
unsigned int width, unsigned int flags)
|
||||
{
|
||||
const size_t start_idx = idx;
|
||||
|
||||
// pad spaces up to given width
|
||||
if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
|
||||
size_t i;
|
||||
for(i = len; i < width; i++) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
// reverse string
|
||||
while(len) {
|
||||
out(buf[--len], buffer, idx++, maxlen);
|
||||
}
|
||||
|
||||
// append pad spaces up to given width
|
||||
if(flags & FLAGS_LEFT) {
|
||||
while(idx - start_idx < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
// internal itoa format
|
||||
static size_t _ntoa_format(out_fct_type out, char * buffer, size_t idx, size_t maxlen, char * buf, size_t len,
|
||||
bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
// pad leading zeros
|
||||
if(!(flags & FLAGS_LEFT)) {
|
||||
if(width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
while((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
// handle hash
|
||||
if(flags & FLAGS_HASH) {
|
||||
if(!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
|
||||
len--;
|
||||
if(len && (base == 16U)) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'x';
|
||||
}
|
||||
else if((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'X';
|
||||
}
|
||||
else if((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'b';
|
||||
}
|
||||
if(len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if(len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
if(negative) {
|
||||
buf[len++] = '-';
|
||||
}
|
||||
else if(flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
}
|
||||
else if(flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
// internal itoa for 'long' type
|
||||
static size_t _ntoa_long(out_fct_type out, char * buffer, size_t idx, size_t maxlen, unsigned long value, bool negative,
|
||||
unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if(!value) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if(!(flags & FLAGS_PRECISION) || value) {
|
||||
do {
|
||||
const char digit = (char)(value % base);
|
||||
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while(value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||
}
|
||||
|
||||
// internal itoa for 'long long' type
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
static size_t _ntoa_long_long(out_fct_type out, char * buffer, size_t idx, size_t maxlen, unsigned long long value,
|
||||
bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if(!value) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if(!(flags & FLAGS_PRECISION) || value) {
|
||||
do {
|
||||
const char digit = (char)(value % base);
|
||||
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while(value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||
}
|
||||
#endif // PRINTF_SUPPORT_LONG_LONG
|
||||
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
|
||||
static size_t _etoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
|
||||
unsigned int width, unsigned int flags);
|
||||
#endif
|
||||
|
||||
// internal ftoa for fixed decimal floating point
|
||||
static size_t _ftoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
|
||||
unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_FTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
double diff = 0.0;
|
||||
|
||||
// powers of 10
|
||||
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
|
||||
// test for special values
|
||||
if(value != value)
|
||||
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
|
||||
if(value < -DBL_MAX)
|
||||
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
|
||||
if(value > DBL_MAX)
|
||||
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width,
|
||||
flags);
|
||||
|
||||
// test for very large values
|
||||
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
|
||||
if((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
#else
|
||||
return 0U;
|
||||
#endif
|
||||
}
|
||||
|
||||
// test for negative
|
||||
bool negative = false;
|
||||
if(value < 0) {
|
||||
negative = true;
|
||||
value = 0 - value;
|
||||
}
|
||||
|
||||
// set default precision, if not set explicitly
|
||||
if(!(flags & FLAGS_PRECISION)) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
|
||||
while((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
|
||||
buf[len++] = '0';
|
||||
prec--;
|
||||
}
|
||||
|
||||
int whole = (int)value;
|
||||
double tmp = (value - whole) * pow10[prec];
|
||||
unsigned long frac = (unsigned long)tmp;
|
||||
diff = tmp - frac;
|
||||
|
||||
if(diff > 0.5) {
|
||||
++frac;
|
||||
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
|
||||
if(frac >= pow10[prec]) {
|
||||
frac = 0;
|
||||
++whole;
|
||||
}
|
||||
}
|
||||
else if(diff < 0.5) {
|
||||
}
|
||||
else if((frac == 0U) || (frac & 1U)) {
|
||||
// if halfway, round up if odd OR if last digit is 0
|
||||
++frac;
|
||||
}
|
||||
|
||||
if(prec == 0U) {
|
||||
diff = value - (double)whole;
|
||||
if((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
|
||||
// exactly 0.5 and ODD, then round up
|
||||
// 1.5 -> 2, but 2.5 -> 2
|
||||
++whole;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned int count = prec;
|
||||
// now do fractional part, as an unsigned number
|
||||
while(len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
--count;
|
||||
buf[len++] = (char)(48U + (frac % 10U));
|
||||
if(!(frac /= 10U)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add extra 0s
|
||||
while((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
if(len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
// add decimal
|
||||
buf[len++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
// do whole part, number is reversed
|
||||
while(len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
buf[len++] = (char)(48 + (whole % 10));
|
||||
if(!(whole /= 10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pad leading zeros
|
||||
if(!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
|
||||
if(width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if(len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
if(negative) {
|
||||
buf[len++] = '-';
|
||||
}
|
||||
else if(flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
}
|
||||
else if(flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
|
||||
static size_t _etoa(out_fct_type out, char * buffer, size_t idx, size_t maxlen, double value, unsigned int prec,
|
||||
unsigned int width, unsigned int flags)
|
||||
{
|
||||
// check for NaN and special values
|
||||
if((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
|
||||
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
}
|
||||
|
||||
// determine the sign
|
||||
const bool negative = value < 0;
|
||||
if(negative) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// default precision
|
||||
if(!(flags & FLAGS_PRECISION)) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
|
||||
// determine the decimal exponent
|
||||
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
|
||||
union {
|
||||
uint64_t U;
|
||||
double F;
|
||||
} conv;
|
||||
|
||||
conv.F = value;
|
||||
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
|
||||
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
|
||||
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
|
||||
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
|
||||
// now we want to compute 10^expval but we want to be sure it won't overflow
|
||||
exp2 = (int)(expval * 3.321928094887362 + 0.5);
|
||||
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
|
||||
const double z2 = z * z;
|
||||
conv.U = (uint64_t)(exp2 + 1023) << 52U;
|
||||
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
|
||||
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
|
||||
// correct for rounding errors
|
||||
if(value < conv.F) {
|
||||
expval--;
|
||||
conv.F /= 10;
|
||||
}
|
||||
|
||||
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
|
||||
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
|
||||
|
||||
// in "%g" mode, "prec" is the number of *significant figures* not decimals
|
||||
if(flags & FLAGS_ADAPT_EXP) {
|
||||
// do we want to fall-back to "%f" mode?
|
||||
if((value >= 1e-4) && (value < 1e6)) {
|
||||
if((int)prec > expval) {
|
||||
prec = (unsigned)((int)prec - expval - 1);
|
||||
}
|
||||
else {
|
||||
prec = 0;
|
||||
}
|
||||
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
|
||||
// no characters in exponent
|
||||
minwidth = 0U;
|
||||
expval = 0;
|
||||
}
|
||||
else {
|
||||
// we use one sigfig for the whole part
|
||||
if((prec > 0) && (flags & FLAGS_PRECISION)) {
|
||||
--prec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will everything fit?
|
||||
unsigned int fwidth = width;
|
||||
if(width > minwidth) {
|
||||
// we didn't fall-back so subtract the characters required for the exponent
|
||||
fwidth -= minwidth;
|
||||
}
|
||||
else {
|
||||
// not enough characters, so go back to default sizing
|
||||
fwidth = 0U;
|
||||
}
|
||||
if((flags & FLAGS_LEFT) && minwidth) {
|
||||
// if we're padding on the right, DON'T pad the floating part
|
||||
fwidth = 0U;
|
||||
}
|
||||
|
||||
// rescale the float value
|
||||
if(expval) {
|
||||
value /= conv.F;
|
||||
}
|
||||
|
||||
// output the floating part
|
||||
const size_t start_idx = idx;
|
||||
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
|
||||
|
||||
// output the exponent part
|
||||
if(minwidth) {
|
||||
// output the exponential symbol
|
||||
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
|
||||
// output the exponent value
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth - 1,
|
||||
FLAGS_ZEROPAD | FLAGS_PLUS);
|
||||
// might need to right-pad spaces
|
||||
if(flags & FLAGS_LEFT) {
|
||||
while(idx - start_idx < width) out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif // PRINTF_SUPPORT_FLOAT
|
||||
|
||||
// internal vsnprintf
|
||||
static int lv_vsnprintf_inner(out_fct_type out, char * buffer, const size_t maxlen, const char * format, va_list va)
|
||||
{
|
||||
unsigned int flags, width, precision, n;
|
||||
size_t idx = 0U;
|
||||
|
||||
if(!buffer) {
|
||||
// use null output function
|
||||
out = _out_null;
|
||||
}
|
||||
|
||||
while(*format) {
|
||||
// format specifier? %[flags][width][.precision][length]
|
||||
if(*format != '%') {
|
||||
// no
|
||||
out(*format, buffer, idx++, maxlen);
|
||||
format++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// yes, evaluate it
|
||||
format++;
|
||||
}
|
||||
|
||||
// evaluate flags
|
||||
flags = 0U;
|
||||
do {
|
||||
switch(*format) {
|
||||
case '0':
|
||||
flags |= FLAGS_ZEROPAD;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '-':
|
||||
flags |= FLAGS_LEFT;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '+':
|
||||
flags |= FLAGS_PLUS;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case ' ':
|
||||
flags |= FLAGS_SPACE;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
case '#':
|
||||
flags |= FLAGS_HASH;
|
||||
format++;
|
||||
n = 1U;
|
||||
break;
|
||||
default :
|
||||
n = 0U;
|
||||
break;
|
||||
}
|
||||
} while(n);
|
||||
|
||||
// evaluate width field
|
||||
width = 0U;
|
||||
if(_is_digit(*format)) {
|
||||
width = _atoi(&format);
|
||||
}
|
||||
else if(*format == '*') {
|
||||
const int w = va_arg(va, int);
|
||||
if(w < 0) {
|
||||
flags |= FLAGS_LEFT; // reverse padding
|
||||
width = (unsigned int) - w;
|
||||
}
|
||||
else {
|
||||
width = (unsigned int)w;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
// evaluate precision field
|
||||
precision = 0U;
|
||||
if(*format == '.') {
|
||||
flags |= FLAGS_PRECISION;
|
||||
format++;
|
||||
if(_is_digit(*format)) {
|
||||
precision = _atoi(&format);
|
||||
}
|
||||
else if(*format == '*') {
|
||||
const int prec = (int)va_arg(va, int);
|
||||
precision = prec > 0 ? (unsigned int)prec : 0U;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate length field
|
||||
switch(*format) {
|
||||
case 'l' :
|
||||
flags |= FLAGS_LONG;
|
||||
format++;
|
||||
if(*format == 'l') {
|
||||
flags |= FLAGS_LONG_LONG;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 'h' :
|
||||
flags |= FLAGS_SHORT;
|
||||
format++;
|
||||
if(*format == 'h') {
|
||||
flags |= FLAGS_CHAR;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
|
||||
case 't' :
|
||||
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
#endif
|
||||
case 'j' :
|
||||
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
case 'z' :
|
||||
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
// evaluate specifier
|
||||
switch(*format) {
|
||||
case 'd' :
|
||||
case 'i' :
|
||||
case 'u' :
|
||||
case 'x' :
|
||||
case 'X' :
|
||||
case 'p' :
|
||||
case 'P' :
|
||||
case 'o' :
|
||||
case 'b' : {
|
||||
// set the base
|
||||
unsigned int base;
|
||||
if(*format == 'x' || *format == 'X') {
|
||||
base = 16U;
|
||||
}
|
||||
else if(*format == 'p' || *format == 'P') {
|
||||
base = 16U;
|
||||
flags |= FLAGS_HASH; // always hash for pointer format
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
if(sizeof(uintptr_t) == sizeof(long long))
|
||||
flags |= FLAGS_LONG_LONG;
|
||||
else
|
||||
#endif
|
||||
flags |= FLAGS_LONG;
|
||||
|
||||
if(*(format + 1) == 'V')
|
||||
format++;
|
||||
}
|
||||
else if(*format == 'o') {
|
||||
base = 8U;
|
||||
}
|
||||
else if(*format == 'b') {
|
||||
base = 2U;
|
||||
}
|
||||
else {
|
||||
base = 10U;
|
||||
flags &= ~FLAGS_HASH; // no hash for dec format
|
||||
}
|
||||
// uppercase
|
||||
if(*format == 'X' || *format == 'P') {
|
||||
flags |= FLAGS_UPPERCASE;
|
||||
}
|
||||
|
||||
// no plus or space flag for u, x, X, o, b
|
||||
if((*format != 'i') && (*format != 'd')) {
|
||||
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
|
||||
}
|
||||
|
||||
// ignore '0' flag when precision is given
|
||||
if(flags & FLAGS_PRECISION) {
|
||||
flags &= ~FLAGS_ZEROPAD;
|
||||
}
|
||||
|
||||
// convert the integer
|
||||
if((*format == 'i') || (*format == 'd')) {
|
||||
// signed
|
||||
if(flags & FLAGS_LONG_LONG) {
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
const long long value = va_arg(va, long long);
|
||||
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base,
|
||||
precision, width, flags);
|
||||
#endif
|
||||
}
|
||||
else if(flags & FLAGS_LONG) {
|
||||
const long value = va_arg(va, long);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision,
|
||||
width, flags);
|
||||
}
|
||||
else {
|
||||
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va,
|
||||
int) : va_arg(va, int);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision,
|
||||
width, flags);
|
||||
}
|
||||
}
|
||||
else if(*format == 'V') {
|
||||
lv_vaformat_t * vaf = va_arg(va, lv_vaformat_t *);
|
||||
va_list copy;
|
||||
|
||||
va_copy(copy, *vaf->va);
|
||||
idx += lv_vsnprintf_inner(out, buffer + idx, maxlen - idx, vaf->fmt, copy);
|
||||
va_end(copy);
|
||||
}
|
||||
else {
|
||||
// unsigned
|
||||
if(flags & FLAGS_LONG_LONG) {
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
|
||||
#endif
|
||||
}
|
||||
else if(flags & FLAGS_LONG) {
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
|
||||
}
|
||||
else {
|
||||
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va,
|
||||
unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
case 'f' :
|
||||
case 'F' :
|
||||
if(*format == 'F') flags |= FLAGS_UPPERCASE;
|
||||
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||
format++;
|
||||
break;
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
if((*format == 'g') || (*format == 'G')) flags |= FLAGS_ADAPT_EXP;
|
||||
if((*format == 'E') || (*format == 'G')) flags |= FLAGS_UPPERCASE;
|
||||
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||
format++;
|
||||
break;
|
||||
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif // PRINTF_SUPPORT_FLOAT
|
||||
case 'c' : {
|
||||
unsigned int l = 1U;
|
||||
// pre padding
|
||||
if(!(flags & FLAGS_LEFT)) {
|
||||
while(l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// char output
|
||||
out((char)va_arg(va, int), buffer, idx++, maxlen);
|
||||
// post padding
|
||||
if(flags & FLAGS_LEFT) {
|
||||
while(l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's' : {
|
||||
const char * p = va_arg(va, char *);
|
||||
unsigned int l = _strnlen_s(p, precision ? precision : (size_t) -1);
|
||||
// pre padding
|
||||
if(flags & FLAGS_PRECISION) {
|
||||
l = (l < precision ? l : precision);
|
||||
}
|
||||
if(!(flags & FLAGS_LEFT)) {
|
||||
while(l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// string output
|
||||
while((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
|
||||
out(*(p++), buffer, idx++, maxlen);
|
||||
}
|
||||
// post padding
|
||||
if(flags & FLAGS_LEFT) {
|
||||
while(l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case '%' :
|
||||
out('%', buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
|
||||
default :
|
||||
out(*format, buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// termination
|
||||
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
||||
|
||||
// return written chars without terminating \0
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// GLOBAL FUNCTIONS FOR LVGL
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int lv_snprintf(char * buffer, size_t count, const char * format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int ret = lv_vsnprintf_inner(_out_buffer, buffer, count, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va)
|
||||
{
|
||||
return lv_vsnprintf_inner(_out_buffer, buffer, count, format, va);
|
||||
}
|
||||
|
||||
#endif /*LV_STDLIB_BUILTIN*/
|
||||
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* @file lv_string.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_STRING == LV_STDLIB_BUILTIN
|
||||
#include "../../misc/lv_assert.h"
|
||||
#include "../../misc/lv_log.h"
|
||||
#include "../../misc/lv_math.h"
|
||||
#include "../../stdlib/lv_string.h"
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#ifdef LV_ARCH_64
|
||||
#define MEM_UNIT uint64_t
|
||||
#define ALIGN_MASK 0x7
|
||||
#else
|
||||
#define MEM_UNIT uint32_t
|
||||
#define ALIGN_MASK 0x3
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_MEM
|
||||
#define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define LV_TRACE_MEM(...)
|
||||
#endif
|
||||
|
||||
#define _COPY(d, s) *d = *s; d++; s++;
|
||||
#define _SET(d, v) *d = v; d++;
|
||||
#define _REPEAT8(expr) expr expr expr expr expr expr expr expr
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memcpy(void * dst, const void * src, size_t len)
|
||||
{
|
||||
uint8_t * d8 = dst;
|
||||
const uint8_t * s8 = src;
|
||||
|
||||
/*Simplify for small memories*/
|
||||
if(len < 16) {
|
||||
while(len) {
|
||||
*d8 = *s8;
|
||||
d8++;
|
||||
s8++;
|
||||
len--;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
lv_uintptr_t d_align = (lv_uintptr_t)d8 & ALIGN_MASK;
|
||||
lv_uintptr_t s_align = (lv_uintptr_t)s8 & ALIGN_MASK;
|
||||
|
||||
/*Byte copy for unaligned memories*/
|
||||
if(s_align != d_align) {
|
||||
while(len > 32) {
|
||||
_REPEAT8(_COPY(d8, s8));
|
||||
_REPEAT8(_COPY(d8, s8));
|
||||
_REPEAT8(_COPY(d8, s8));
|
||||
_REPEAT8(_COPY(d8, s8));
|
||||
len -= 32;
|
||||
}
|
||||
while(len) {
|
||||
_COPY(d8, s8)
|
||||
len--;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/*Make the memories aligned*/
|
||||
if(d_align) {
|
||||
d_align = ALIGN_MASK + 1 - d_align;
|
||||
while(d_align && len) {
|
||||
_COPY(d8, s8);
|
||||
d_align--;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t * d32 = (uint32_t *)d8;
|
||||
const uint32_t * s32 = (uint32_t *)s8;
|
||||
while(len > 32) {
|
||||
_REPEAT8(_COPY(d32, s32))
|
||||
len -= 32;
|
||||
}
|
||||
|
||||
d8 = (uint8_t *)d32;
|
||||
s8 = (const uint8_t *)s32;
|
||||
while(len) {
|
||||
_COPY(d8, s8)
|
||||
len--;
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void LV_ATTRIBUTE_FAST_MEM lv_memset(void * dst, uint8_t v, size_t len)
|
||||
{
|
||||
uint8_t * d8 = (uint8_t *)dst;
|
||||
uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
|
||||
|
||||
/*Make the address aligned*/
|
||||
if(d_align) {
|
||||
d_align = ALIGN_MASK + 1 - d_align;
|
||||
while(d_align && len) {
|
||||
_SET(d8, v);
|
||||
len--;
|
||||
d_align--;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t v32 = (uint32_t)v + ((uint32_t)v << 8) + ((uint32_t)v << 16) + ((uint32_t)v << 24);
|
||||
uint32_t * d32 = (uint32_t *)d8;
|
||||
|
||||
while(len > 32) {
|
||||
_REPEAT8(_SET(d32, v32));
|
||||
len -= 32;
|
||||
}
|
||||
|
||||
d8 = (uint8_t *)d32;
|
||||
while(len) {
|
||||
_SET(d8, v);
|
||||
len--;
|
||||
}
|
||||
}
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memmove(void * dst, const void * src, size_t len)
|
||||
{
|
||||
if(dst < src || (char *)dst > ((char *)src + len)) {
|
||||
return lv_memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
if(dst > src) {
|
||||
char * tmp = (char *)dst + len - 1;
|
||||
char * s = (char *)src + len - 1;
|
||||
|
||||
while(len--) {
|
||||
*tmp-- = *s--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char * tmp = (char *)dst;
|
||||
char * s = (char *)src;
|
||||
|
||||
while(len--) {
|
||||
*tmp++ = *s++;
|
||||
}
|
||||
}
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
int lv_memcmp(const void * p1, const void * p2, size_t len)
|
||||
{
|
||||
const char * s1 = (const char *) p1;
|
||||
const char * s2 = (const char *) p2;
|
||||
while(--len > 0 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
/* See https://en.cppreference.com/w/c/string/byte/strlen for reference */
|
||||
size_t lv_strlen(const char * str)
|
||||
{
|
||||
size_t i = 0;
|
||||
while(str[i]) i++;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
size_t lv_strlcpy(char * dst, const char * src, size_t dst_size)
|
||||
{
|
||||
size_t i = 0;
|
||||
if(dst_size > 0) {
|
||||
for(; i < dst_size - 1 && src[i]; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
dst[i] = '\0';
|
||||
}
|
||||
while(src[i]) i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
char * lv_strncpy(char * dst, const char * src, size_t dst_size)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < dst_size && src[i]; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
for(; i < dst_size; i++) {
|
||||
dst[i] = '\0';
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strcpy(char * dst, const char * src)
|
||||
{
|
||||
char * tmp = dst;
|
||||
while((*dst++ = *src++) != '\0');
|
||||
return tmp;
|
||||
}
|
||||
|
||||
int lv_strcmp(const char * s1, const char * s2)
|
||||
{
|
||||
while(*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
return *(const unsigned char *)s1 - *(const unsigned char *)s2;
|
||||
}
|
||||
|
||||
char * lv_strdup(const char * src)
|
||||
{
|
||||
size_t len = lv_strlen(src) + 1;
|
||||
char * dst = lv_malloc(len);
|
||||
if(dst == NULL) return NULL;
|
||||
|
||||
lv_memcpy(dst, src, len); /*memcpy is faster than strncpy when length is known*/
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strcat(char * dst, const char * src)
|
||||
{
|
||||
lv_strcpy(dst + lv_strlen(dst), src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
{
|
||||
char * tmp = dst;
|
||||
while(*dst != '\0') {
|
||||
dst++;
|
||||
}
|
||||
while(src_len != 0 && *src != '\0') {
|
||||
src_len--;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_BUILTIN*/
|
||||
1245
software/Power_Pico/Middlewares/LVGL/src/stdlib/builtin/lv_tlsf.c
Normal file
1245
software/Power_Pico/Middlewares/LVGL/src/stdlib/builtin/lv_tlsf.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN
|
||||
|
||||
#ifndef LV_TLSF_H
|
||||
#define LV_TLSF_H
|
||||
|
||||
/*
|
||||
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||
** Written by Matthew Conte
|
||||
** http://tlsf.baisoku.org
|
||||
**
|
||||
** Based on the original documentation by Miguel Masmano:
|
||||
** http://www.gii.upv.es/tlsf/main/docs
|
||||
**
|
||||
** This implementation was written to the specification
|
||||
** of the document, therefore no GPL restrictions apply.
|
||||
**
|
||||
** Copyright (c) 2006-2016, Matthew Conte
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the copyright holder nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../../osal/lv_os.h"
|
||||
#include "../../misc/lv_ll.h"
|
||||
#include "../../misc/lv_types.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* lv_tlsf_t: a TLSF structure. Can contain 1 to N pools. */
|
||||
/* lv_pool_t: a block of memory that TLSF can manage. */
|
||||
typedef void * lv_tlsf_t;
|
||||
typedef void * lv_pool_t;
|
||||
|
||||
/* Create/destroy a memory pool. */
|
||||
lv_tlsf_t lv_tlsf_create(void * mem);
|
||||
lv_tlsf_t lv_tlsf_create_with_pool(void * mem, size_t bytes);
|
||||
void lv_tlsf_destroy(lv_tlsf_t tlsf);
|
||||
lv_pool_t lv_tlsf_get_pool(lv_tlsf_t tlsf);
|
||||
|
||||
/* Add/remove memory pools. */
|
||||
lv_pool_t lv_tlsf_add_pool(lv_tlsf_t tlsf, void * mem, size_t bytes);
|
||||
void lv_tlsf_remove_pool(lv_tlsf_t tlsf, lv_pool_t pool);
|
||||
|
||||
/* malloc/memalign/realloc/free replacements. */
|
||||
void * lv_tlsf_malloc(lv_tlsf_t tlsf, size_t bytes);
|
||||
void * lv_tlsf_memalign(lv_tlsf_t tlsf, size_t align, size_t bytes);
|
||||
void * lv_tlsf_realloc(lv_tlsf_t tlsf, void * ptr, size_t size);
|
||||
size_t lv_tlsf_free(lv_tlsf_t tlsf, const void * ptr);
|
||||
|
||||
/* Returns internal block size, not original request size */
|
||||
size_t lv_tlsf_block_size(void * ptr);
|
||||
|
||||
/* Overheads/limits of internal structures. */
|
||||
size_t lv_tlsf_size(void);
|
||||
size_t lv_tlsf_align_size(void);
|
||||
size_t lv_tlsf_block_size_min(void);
|
||||
size_t lv_tlsf_block_size_max(void);
|
||||
size_t lv_tlsf_pool_overhead(void);
|
||||
size_t lv_tlsf_alloc_overhead(void);
|
||||
|
||||
/* Debugging. */
|
||||
typedef void (*lv_tlsf_walker)(void * ptr, size_t size, int used, void * user);
|
||||
void lv_tlsf_walk_pool(lv_pool_t pool, lv_tlsf_walker walker, void * user);
|
||||
/* Returns nonzero if any internal consistency check fails. */
|
||||
int lv_tlsf_check(lv_tlsf_t tlsf);
|
||||
int lv_tlsf_check_pool(lv_pool_t pool);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /*LV_TLSF_H*/
|
||||
|
||||
#endif /*LV_STDLIB_BUILTIN*/
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @file lv_tlsf_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_TLSF_PRIVATE_H
|
||||
#define LV_TLSF_PRIVATE_H
|
||||
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_tlsf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct {
|
||||
#if LV_USE_OS
|
||||
lv_mutex_t mutex;
|
||||
#endif
|
||||
lv_tlsf_t tlsf;
|
||||
size_t cur_used;
|
||||
size_t max_used;
|
||||
lv_ll_t pool_ll;
|
||||
} lv_tlsf_state_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN*/
|
||||
|
||||
#endif /*LV_TLSF_PRIVATE_H*/
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @file lv_malloc_core.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_mem.h"
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_CLIB
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
return; /*Nothing to init*/
|
||||
}
|
||||
|
||||
void lv_mem_deinit(void)
|
||||
{
|
||||
return; /*Nothing to deinit*/
|
||||
|
||||
}
|
||||
|
||||
lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mem);
|
||||
LV_UNUSED(bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lv_mem_remove_pool(lv_mem_pool_t pool)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
void * lv_malloc_core(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void * lv_realloc_core(void * p, size_t new_size)
|
||||
{
|
||||
return realloc(p, new_size);
|
||||
}
|
||||
|
||||
void lv_free_core(void * p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mon_p);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_result_t lv_mem_test_core(void)
|
||||
{
|
||||
/*Not supported*/
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_CLIB*/
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
/**
|
||||
* @file lv_templ.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_CLIB
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "../lv_sprintf.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
int lv_snprintf(char * buffer, size_t count, const char * format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int ret = vsnprintf(buffer, count, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va)
|
||||
{
|
||||
return vsnprintf(buffer, count, format, va);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @file lv_string.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_STRING == LV_STDLIB_CLIB
|
||||
#include "../lv_string.h"
|
||||
#include "../lv_mem.h" /*Need lv_malloc*/
|
||||
#include <string.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memcpy(void * dst, const void * src, size_t len)
|
||||
{
|
||||
return memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
void LV_ATTRIBUTE_FAST_MEM lv_memset(void * dst, uint8_t v, size_t len)
|
||||
{
|
||||
memset(dst, v, len);
|
||||
}
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memmove(void * dst, const void * src, size_t len)
|
||||
{
|
||||
return memmove(dst, src, len);
|
||||
}
|
||||
|
||||
int lv_memcmp(const void * p1, const void * p2, size_t len)
|
||||
{
|
||||
return memcmp(p1, p2, len);
|
||||
}
|
||||
|
||||
size_t lv_strlen(const char * str)
|
||||
{
|
||||
return strlen(str);
|
||||
}
|
||||
|
||||
size_t lv_strlcpy(char * dst, const char * src, size_t dst_size)
|
||||
{
|
||||
size_t src_len = strlen(src);
|
||||
if(dst_size > 0) {
|
||||
size_t copy_size = src_len < dst_size ? src_len : dst_size - 1;
|
||||
memcpy(dst, src, copy_size);
|
||||
dst[copy_size] = '\0';
|
||||
}
|
||||
return src_len;
|
||||
}
|
||||
|
||||
char * lv_strncpy(char * dst, const char * src, size_t dest_size)
|
||||
{
|
||||
return strncpy(dst, src, dest_size);
|
||||
}
|
||||
|
||||
char * lv_strcpy(char * dst, const char * src)
|
||||
{
|
||||
return strcpy(dst, src);
|
||||
}
|
||||
|
||||
int lv_strcmp(const char * s1, const char * s2)
|
||||
{
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
char * lv_strdup(const char * src)
|
||||
{
|
||||
/*strdup uses malloc, so use the lv_malloc when LV_USE_STDLIB_MALLOC is not LV_STDLIB_CLIB */
|
||||
size_t len = lv_strlen(src) + 1;
|
||||
char * dst = lv_malloc(len);
|
||||
if(dst == NULL) return NULL;
|
||||
|
||||
lv_memcpy(dst, src, len); /*do memcpy is faster than strncpy when length is known*/
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strcat(char * dst, const char * src)
|
||||
{
|
||||
return strcat(dst, src);
|
||||
}
|
||||
|
||||
char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
{
|
||||
return strncat(dst, src, src_len);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_CLIB*/
|
||||
168
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_mem.c
Normal file
168
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_mem.c
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* @file lv_mem.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_mem_private.h"
|
||||
#include "lv_string.h"
|
||||
#include "../misc/lv_assert.h"
|
||||
#include "../misc/lv_log.h"
|
||||
#include "../core/lv_global.h"
|
||||
|
||||
#if LV_USE_OS == LV_OS_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
/*memset the allocated memories to 0xaa and freed memories to 0xbb (just for testing purposes)*/
|
||||
#ifndef LV_MEM_ADD_JUNK
|
||||
#define LV_MEM_ADD_JUNK 0
|
||||
#endif
|
||||
|
||||
#define zero_mem LV_GLOBAL_DEFAULT()->memory_zero
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
void * lv_malloc_core(size_t size);
|
||||
void * lv_realloc_core(void * p, size_t new_size);
|
||||
void lv_free_core(void * p);
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p);
|
||||
lv_result_t lv_mem_test_core(void);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
#if LV_USE_LOG && LV_LOG_TRACE_MEM
|
||||
#define LV_TRACE_MEM(...) LV_LOG_TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define LV_TRACE_MEM(...)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void * lv_malloc(size_t size)
|
||||
{
|
||||
LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size);
|
||||
if(size == 0) {
|
||||
LV_TRACE_MEM("using zero_mem");
|
||||
return &zero_mem;
|
||||
}
|
||||
|
||||
void * alloc = lv_malloc_core(size);
|
||||
|
||||
if(alloc == NULL) {
|
||||
LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size);
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
|
||||
lv_mem_monitor_t mon;
|
||||
lv_mem_monitor(&mon);
|
||||
LV_LOG_INFO("used: %zu (%3d %%), frag: %3d %%, biggest free: %zu",
|
||||
mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct,
|
||||
mon.free_biggest_size);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if LV_MEM_ADD_JUNK
|
||||
lv_memset(alloc, 0xaa, size);
|
||||
#endif
|
||||
|
||||
LV_TRACE_MEM("allocated at %p", alloc);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void * lv_malloc_zeroed(size_t size)
|
||||
{
|
||||
LV_TRACE_MEM("allocating %lu bytes", (unsigned long)size);
|
||||
if(size == 0) {
|
||||
LV_TRACE_MEM("using zero_mem");
|
||||
return &zero_mem;
|
||||
}
|
||||
|
||||
void * alloc = lv_malloc_core(size);
|
||||
if(alloc == NULL) {
|
||||
LV_LOG_INFO("couldn't allocate memory (%lu bytes)", (unsigned long)size);
|
||||
#if LV_LOG_LEVEL <= LV_LOG_LEVEL_INFO
|
||||
lv_mem_monitor_t mon;
|
||||
lv_mem_monitor(&mon);
|
||||
LV_LOG_INFO("used: %zu (%3d %%), frag: %3d %%, biggest free: %zu",
|
||||
mon.total_size - mon.free_size, mon.used_pct, mon.frag_pct,
|
||||
mon.free_biggest_size);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lv_memzero(alloc, size);
|
||||
|
||||
LV_TRACE_MEM("allocated at %p", alloc);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void lv_free(void * data)
|
||||
{
|
||||
LV_TRACE_MEM("freeing %p", data);
|
||||
if(data == &zero_mem) return;
|
||||
if(data == NULL) return;
|
||||
|
||||
lv_free_core(data);
|
||||
}
|
||||
|
||||
void * lv_realloc(void * data_p, size_t new_size)
|
||||
{
|
||||
LV_TRACE_MEM("reallocating %p with %lu size", data_p, (unsigned long)new_size);
|
||||
if(new_size == 0) {
|
||||
LV_TRACE_MEM("using zero_mem");
|
||||
lv_free(data_p);
|
||||
return &zero_mem;
|
||||
}
|
||||
|
||||
if(data_p == &zero_mem) return lv_malloc(new_size);
|
||||
|
||||
void * new_p = lv_realloc_core(data_p, new_size);
|
||||
|
||||
if(new_p == NULL) {
|
||||
LV_LOG_ERROR("couldn't reallocate memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LV_TRACE_MEM("reallocated at %p", new_p);
|
||||
return new_p;
|
||||
}
|
||||
|
||||
lv_result_t lv_mem_test(void)
|
||||
{
|
||||
if(zero_mem != ZERO_MEM_SENTINEL) {
|
||||
LV_LOG_WARN("zero_mem is written");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
return lv_mem_test_core();
|
||||
}
|
||||
|
||||
void lv_mem_monitor(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
lv_memzero(mon_p, sizeof(lv_mem_monitor_t));
|
||||
lv_mem_monitor_core(mon_p);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
141
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_mem.h
Normal file
141
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_mem.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file lv_mem.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MEM_H
|
||||
#define LV_MEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
|
||||
#include "lv_string.h"
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef void * lv_mem_pool_t;
|
||||
|
||||
/**
|
||||
* Heap information structure.
|
||||
*/
|
||||
typedef struct {
|
||||
size_t total_size; /**< Total heap size */
|
||||
size_t free_cnt;
|
||||
size_t free_size; /**< Size of available memory */
|
||||
size_t free_biggest_size;
|
||||
size_t used_cnt;
|
||||
size_t max_used; /**< Max size of Heap memory used */
|
||||
uint8_t used_pct; /**< Percentage used */
|
||||
uint8_t frag_pct; /**< Amount of fragmentation */
|
||||
} lv_mem_monitor_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Initialize to use malloc/free/realloc etc
|
||||
*/
|
||||
void lv_mem_init(void);
|
||||
|
||||
/**
|
||||
* Drop all dynamically allocated memory and reset the memory pools' state
|
||||
*/
|
||||
void lv_mem_deinit(void);
|
||||
|
||||
lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes);
|
||||
|
||||
void lv_mem_remove_pool(lv_mem_pool_t pool);
|
||||
|
||||
/**
|
||||
* Allocate memory dynamically
|
||||
* @param size requested size in bytes
|
||||
* @return pointer to allocated uninitialized memory, or NULL on failure
|
||||
*/
|
||||
void * lv_malloc(size_t size);
|
||||
|
||||
/**
|
||||
* Allocate zeroed memory dynamically
|
||||
* @param size requested size in bytes
|
||||
* @return pointer to allocated zeroed memory, or NULL on failure
|
||||
*/
|
||||
void * lv_malloc_zeroed(size_t size);
|
||||
|
||||
/**
|
||||
* Free an allocated data
|
||||
* @param data pointer to an allocated memory
|
||||
*/
|
||||
void lv_free(void * data);
|
||||
|
||||
/**
|
||||
* Reallocate a memory with a new size. The old content will be kept.
|
||||
* @param data_p pointer to an allocated memory.
|
||||
* Its content will be copied to the new memory block and freed
|
||||
* @param new_size the desired new size in byte
|
||||
* @return pointer to the new memory, NULL on failure
|
||||
*/
|
||||
void * lv_realloc(void * data_p, size_t new_size);
|
||||
|
||||
/**
|
||||
* Used internally to execute a plain `malloc` operation
|
||||
* @param size size in bytes to `malloc`
|
||||
*/
|
||||
void * lv_malloc_core(size_t size);
|
||||
|
||||
/**
|
||||
* Used internally to execute a plain `free` operation
|
||||
* @param p memory address to free
|
||||
*/
|
||||
void lv_free_core(void * p);
|
||||
|
||||
/**
|
||||
* Used internally to execute a plain realloc operation
|
||||
* @param p memory address to realloc
|
||||
* @param new_size size in bytes to realloc
|
||||
*/
|
||||
void * lv_realloc_core(void * p, size_t new_size);
|
||||
|
||||
/**
|
||||
* Used internally by lv_mem_monitor() to gather LVGL heap state information.
|
||||
* @param mon_p pointer to lv_mem_monitor_t object to be populated.
|
||||
*/
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p);
|
||||
|
||||
lv_result_t lv_mem_test_core(void);
|
||||
|
||||
/**
|
||||
* @brief Tests the memory allocation system by allocating and freeing a block of memory.
|
||||
* @return LV_RESULT_OK if the memory allocation system is working properly, or LV_RESULT_INVALID if there is an error.
|
||||
*/
|
||||
lv_result_t lv_mem_test(void);
|
||||
|
||||
/**
|
||||
* Give information about the work memory of dynamic allocation
|
||||
* @param mon_p pointer to a lv_mem_monitor_t variable,
|
||||
* the result of the analysis will be stored here
|
||||
*/
|
||||
void lv_mem_monitor(lv_mem_monitor_t * mon_p);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MEM_H*/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file lv_mem_private.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_MEM_PRIVATE_H
|
||||
#define LV_MEM_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_mem.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_MEM_PRIVATE_H*/
|
||||
45
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_sprintf.h
Normal file
45
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_sprintf.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file lv_sprintf.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_SPRINTF_H
|
||||
#define LV_SPRINTF_H
|
||||
|
||||
#if defined(__has_include)
|
||||
#if __has_include(LV_INTTYPES_INCLUDE)
|
||||
#include LV_INTTYPES_INCLUDE
|
||||
/* platform-specific printf format for int32_t, usually "d" or "ld" */
|
||||
#define LV_PRId32 PRId32
|
||||
#define LV_PRIu32 PRIu32
|
||||
#define LV_PRIx32 PRIx32
|
||||
#define LV_PRIX32 PRIX32
|
||||
#else
|
||||
#define LV_PRId32 "d"
|
||||
#define LV_PRIu32 "u"
|
||||
#define LV_PRIx32 "x"
|
||||
#define LV_PRIX32 "X"
|
||||
#endif
|
||||
#else
|
||||
/* hope this is correct for ports without __has_include or without inttypes.h */
|
||||
#define LV_PRId32 "d"
|
||||
#define LV_PRIu32 "u"
|
||||
#define LV_PRIx32 "x"
|
||||
#define LV_PRIX32 "X"
|
||||
#endif
|
||||
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int lv_snprintf(char * buffer, size_t count, const char * format, ...);
|
||||
|
||||
int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_SPRINTF_H */
|
||||
158
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_string.h
Normal file
158
software/Power_Pico/Middlewares/LVGL/src/stdlib/lv_string.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* @file lv_string.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_STRING_H
|
||||
#define LV_STRING_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_conf_internal.h"
|
||||
#include "../misc/lv_types.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* @brief Copies a block of memory from a source address to a destination address.
|
||||
* @param dst Pointer to the destination array where the content is to be copied.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @param len Number of bytes to copy.
|
||||
* @return Pointer to the destination array.
|
||||
* @note The function does not check for any overlapping of the source and destination memory blocks.
|
||||
*/
|
||||
void * lv_memcpy(void * dst, const void * src, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Fills a block of memory with a specified value.
|
||||
* @param dst Pointer to the destination array to fill with the specified value.
|
||||
* @param v Value to be set. The value is passed as an int, but the function fills
|
||||
* the block of memory using the unsigned char conversion of this value.
|
||||
* @param len Number of bytes to be set to the value.
|
||||
*/
|
||||
void lv_memset(void * dst, uint8_t v, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Move a block of memory from source to destination
|
||||
* @param dst Pointer to the destination array where the content is to be copied.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @param len Number of bytes to copy
|
||||
* @return Pointer to the destination array.
|
||||
*/
|
||||
void * lv_memmove(void * dst, const void * src, size_t len);
|
||||
|
||||
/**
|
||||
* @brief This function will compare two memory blocks
|
||||
* @param p1 Pointer to the first memory block
|
||||
* @param p2 Pointer to the second memory block
|
||||
* @param len Number of bytes to compare
|
||||
* @return The difference between the value of the first unmatching byte.
|
||||
*/
|
||||
int lv_memcmp(const void * p1, const void * p2, size_t len);
|
||||
|
||||
/**
|
||||
* Same as `memset(dst, 0x00, len)`.
|
||||
* @param dst pointer to the destination buffer
|
||||
* @param len number of byte to set
|
||||
*/
|
||||
static inline void lv_memzero(void * dst, size_t len)
|
||||
{
|
||||
lv_memset(dst, 0x00, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the length of the string str up to, but not including the terminating null character.
|
||||
* @param str Pointer to the null-terminated byte string to be examined.
|
||||
* @return The length of the string in bytes.
|
||||
*/
|
||||
size_t lv_strlen(const char * str);
|
||||
|
||||
/**
|
||||
* @brief Copies up to dst_size-1 (non-null) characters from src to dst. A null terminator is always added.
|
||||
* @param dst Pointer to the destination array where the content is to be copied.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @param dst_size Maximum number of characters to be copied to dst, including the null character.
|
||||
* @return The length of src. The return value is equivalent to the value returned by lv_strlen(src)
|
||||
*/
|
||||
size_t lv_strlcpy(char * dst, const char * src, size_t dst_size);
|
||||
|
||||
/**
|
||||
* @brief Copies up to dest_size characters from the string pointed to by src to the character array pointed to by dst
|
||||
* and fills the remaining length with null bytes.
|
||||
* @param dst Pointer to the destination array where the content is to be copied.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @param dest_size Maximum number of characters to be copied to dst.
|
||||
* @return A pointer to the destination array, which is dst.
|
||||
* @note dst will not be null terminated if dest_size bytes were copied from src before the end of src was reached.
|
||||
*/
|
||||
char * lv_strncpy(char * dst, const char * src, size_t dest_size);
|
||||
|
||||
/**
|
||||
* @brief Copies the string pointed to by src, including the terminating null character,
|
||||
* to the character array pointed to by dst.
|
||||
* @param dst Pointer to the destination array where the content is to be copied.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @return A pointer to the destination array, which is dst.
|
||||
*/
|
||||
char * lv_strcpy(char * dst, const char * src);
|
||||
|
||||
/**
|
||||
* @brief This function will compare two strings without specified length.
|
||||
* @param s1 pointer to the first string
|
||||
* @param s2 pointer to the second string
|
||||
* @return the difference between the value of the first unmatching character.
|
||||
*/
|
||||
int lv_strcmp(const char * s1, const char * s2);
|
||||
|
||||
/**
|
||||
* @brief Duplicate a string by allocating a new one and copying the content.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @return A pointer to the new allocated string. NULL if failed.
|
||||
*/
|
||||
char * lv_strdup(const char * src);
|
||||
|
||||
/**
|
||||
* @brief Copies the string pointed to by src, including the terminating null character,
|
||||
* to the end of the string pointed to by dst.
|
||||
* @param dst Pointer to the destination string where the content is to be appended.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @return A pointer to the destination string, which is dst.
|
||||
*/
|
||||
char * lv_strcat(char * dst, const char * src);
|
||||
|
||||
/**
|
||||
* @brief Copies up to src_len characters from the string pointed to by src
|
||||
* to the end of the string pointed to by dst.
|
||||
* A terminating null character is appended to dst even if no null character
|
||||
* was encountered in src after src_len characters were copied.
|
||||
* @param dst Pointer to the destination string where the content is to be appended.
|
||||
* @param src Pointer to the source of data to be copied.
|
||||
* @param src_len Maximum number of characters from src to be copied to the end of dst.
|
||||
* @return A pointer to the destination string, which is dst.
|
||||
*/
|
||||
char * lv_strncat(char * dst, const char * src, size_t src_len);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_STRING_H*/
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* @file lv_malloc_core.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_mem.h"
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_MICROPYTHON
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include "include/lv_mp_mem_custom_include.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
return; /*Nothing to init*/
|
||||
}
|
||||
|
||||
void lv_mem_deinit(void)
|
||||
{
|
||||
return; /*Nothing to deinit*/
|
||||
|
||||
}
|
||||
|
||||
lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mem);
|
||||
LV_UNUSED(bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lv_mem_remove_pool(lv_mem_pool_t pool)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
void * lv_malloc_core(size_t size)
|
||||
{
|
||||
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
|
||||
return gc_alloc(size, true);
|
||||
#else
|
||||
return m_malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void * lv_realloc_core(void * p, size_t new_size)
|
||||
{
|
||||
|
||||
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
|
||||
return gc_realloc(p, new_size, true);
|
||||
#else
|
||||
return m_realloc(p, new_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_free_core(void * p)
|
||||
{
|
||||
|
||||
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
|
||||
gc_free(p);
|
||||
|
||||
#else
|
||||
m_free(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mon_p);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_result_t lv_mem_test_core(void)
|
||||
{
|
||||
/*Not supported*/
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_MICROPYTHON*/
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file lv_malloc_core_rtthread.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../lv_mem.h"
|
||||
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_RTTHREAD
|
||||
#include "../../stdlib/lv_mem.h"
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifndef RT_USING_HEAP
|
||||
#error "lv_mem_core_rtthread: RT_USING_HEAP is required. Define it in rtconfig.h"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void lv_mem_init(void)
|
||||
{
|
||||
return; /*Nothing to init*/
|
||||
}
|
||||
|
||||
void lv_mem_deinit(void)
|
||||
{
|
||||
return; /*Nothing to deinit*/
|
||||
}
|
||||
|
||||
lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mem);
|
||||
LV_UNUSED(bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lv_mem_remove_pool(lv_mem_pool_t pool)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(pool);
|
||||
return;
|
||||
}
|
||||
|
||||
void * lv_malloc_core(size_t size)
|
||||
{
|
||||
return rt_malloc(size);
|
||||
}
|
||||
|
||||
void * lv_realloc_core(void * p, size_t new_size)
|
||||
{
|
||||
return rt_realloc(p, new_size);
|
||||
}
|
||||
|
||||
void lv_free_core(void * p)
|
||||
{
|
||||
rt_free(p);
|
||||
}
|
||||
|
||||
void lv_mem_monitor_core(lv_mem_monitor_t * mon_p)
|
||||
{
|
||||
/*Not supported*/
|
||||
LV_UNUSED(mon_p);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_result_t lv_mem_test_core(void)
|
||||
{
|
||||
/*Not supported*/
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_RTTHREAD*/
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file lv_sprintf_rtthread.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_SPRINTF == LV_STDLIB_RTTHREAD
|
||||
#include <rtthread.h>
|
||||
#include <stdarg.h>
|
||||
#include "../lv_sprintf.h"
|
||||
|
||||
#if LV_USE_FLOAT == 1
|
||||
#warning "lv_sprintf_rtthread: rtthread not support float in sprintf"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
int lv_snprintf(char * buffer, size_t count, const char * format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int ret = rt_vsnprintf(buffer, count, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lv_vsnprintf(char * buffer, size_t count, const char * format, va_list va)
|
||||
{
|
||||
return rt_vsnprintf(buffer, count, format, va);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_RTTHREAD*/
|
||||
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @file lv_string_rtthread.c
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../lv_conf_internal.h"
|
||||
#if LV_USE_STDLIB_STRING == LV_STDLIB_RTTHREAD
|
||||
#include "../lv_string.h"
|
||||
#include "../lv_mem.h" /*Need lv_malloc*/
|
||||
#include <rtthread.h>
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memcpy(void * dst, const void * src, size_t len)
|
||||
{
|
||||
return rt_memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
void LV_ATTRIBUTE_FAST_MEM lv_memset(void * dst, uint8_t v, size_t len)
|
||||
{
|
||||
rt_memset(dst, v, len);
|
||||
}
|
||||
|
||||
void * LV_ATTRIBUTE_FAST_MEM lv_memmove(void * dst, const void * src, size_t len)
|
||||
{
|
||||
return rt_memmove(dst, src, len);
|
||||
}
|
||||
|
||||
size_t lv_strlen(const char * str)
|
||||
{
|
||||
return rt_strlen(str);
|
||||
}
|
||||
|
||||
int lv_memcmp(const void * p1, const void * p2, size_t len)
|
||||
{
|
||||
return rt_memcmp(p1, p2, len);
|
||||
}
|
||||
|
||||
size_t lv_strlcpy(char * dst, const char * src, size_t dst_size)
|
||||
{
|
||||
size_t src_len = lv_strlen(src);
|
||||
if(dst_size > 0) {
|
||||
size_t copy_size = src_len < dst_size ? src_len : dst_size - 1;
|
||||
lv_memcpy(dst, src, copy_size);
|
||||
dst[copy_size] = '\0';
|
||||
}
|
||||
return src_len;
|
||||
}
|
||||
|
||||
char * lv_strncpy(char * dst, const char * src, size_t dest_size)
|
||||
{
|
||||
return rt_strncpy(dst, src, dest_size);
|
||||
}
|
||||
|
||||
char * lv_strcpy(char * dst, const char * src)
|
||||
{
|
||||
return rt_strcpy(dst, src);
|
||||
}
|
||||
|
||||
int lv_strcmp(const char * s1, const char * s2)
|
||||
{
|
||||
return rt_strcmp(s1, s2);
|
||||
}
|
||||
|
||||
char * lv_strdup(const char * src)
|
||||
{
|
||||
size_t len = lv_strlen(src) + 1;
|
||||
char * dst = lv_malloc(len);
|
||||
if(dst == NULL) return NULL;
|
||||
|
||||
lv_memcpy(dst, src, len); /*memcpy is faster than strncpy when length is known*/
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strcat(char * dst, const char * src)
|
||||
{
|
||||
/*Since RT-thread does not have rt_strcat,
|
||||
the following code is used instead.*/
|
||||
lv_strcpy(dst + lv_strlen(dst), src);
|
||||
return dst;
|
||||
}
|
||||
|
||||
char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
{
|
||||
char * tmp = dst;
|
||||
dst += lv_strlen(dst);
|
||||
while(src_len != 0 && *src != '\0') {
|
||||
src_len--;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_STDLIB_RTTHREAD*/
|
||||
Reference in New Issue
Block a user