BLE_TYQ_CH584M/common/lwrb-3.2.0/lwrb_ex.c

163 lines
6.0 KiB
C

/*
* @Author : stark1898y 1658608470@qq.com
* @Date : 2024-12-12 13:35:45
* @LastEditors : stark1898y 1658608470@qq.com
* @LastEditTime : 2024-12-12 13:35:45
* @FilePath : \BLE_TYQ_CH584M\common\lwrb-3.2.0\lwrb_ex.c
* @Description :
*
* Copyright (c) 2024 by yzy, All Rights Reserved.
*/
/**
* \file lwrb_ex.c
* \brief Lightweight ring buffer - extended functions
*/
/*
* Copyright (c) 2024 Tilen MAJERLE
*
* 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.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v3.2.0
*/
#include "lwrb.h"
#if defined(LWRB_DEV)
/* Do not build if development mode isn't enabled */
#define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0)
#define BUF_MIN(x, y) ((x) < (y) ? (x) : (y))
/**
* \brief Writes data to buffer with overwrite function, if no enough space to hold
* complete input data object.
* \note Similar to \ref lwrb_write but overwrites
* \param[in] buff: Buffer handle
* \param[in] data: Data to write to ring buffer
* \param[in] btw: Bytes To Write, length
* \return Number of bytes written to buffer, will always return btw
* \note Functionality is primary two parts, always writes some linear region, then
* writes the wrap region if there is more data to write. The r indicator is advanced if w overtakes
* it. This operation is a read op as well as a write op. For thread-safety mutexes may be desired,
* see documentation.
*/
lwrb_sz_t
lwrb_overwrite(lwrb_t* buff, const void* data, lwrb_sz_t btw) {
lwrb_sz_t orig_btw = btw, max_cap;
const uint8_t* d = data;
if (!BUF_IS_VALID(buff) || data == NULL || btw == 0) {
return 0;
}
/* Process complete input array */
max_cap = buff->size - 1; /* Maximum capacity buffer can hold */
if (btw > max_cap) {
/*
* When data to write is larger than max buffer capacity,
* we can reset the buffer and simply write last part of
* the input buffer.
*
* This is done here, by calculating remaining
* length and then advancing to the end of input buffer
*/
d += btw - max_cap; /* Advance data */
btw = max_cap; /* Limit data to write */
lwrb_reset(buff); /* Reset buffer */
} else {
/*
* Bytes to write is less than capacity
* We have to perform max one skip operation,
* but only if free memory is less than
* btw, otherwise we skip the operation
* and only write the data.
*/
lwrb_sz_t f = lwrb_get_free(buff);
if (f < btw) {
lwrb_skip(buff, btw - f);
}
}
lwrb_write(buff, d, btw);
return orig_btw;
}
/**
* \brief Move one ring buffer to another, up to the amount of data in the source, or amount
* of data free in the destination.
* \param[in] dest: Buffer handle that the copied data will be written to
* \param[in] src: Buffer handle that the copied data will come from.
* Source buffer will be effectively read upon operation.
* \return Number of bytes written to destination buffer
* \note This operation is a read op to the source, on success it will update the r index.
* As well as a write op to the destination, and may update the w index.
* For thread-safety mutexes may be desired, see documentation.
*/
lwrb_sz_t
lwrb_move(lwrb_t* dest, lwrb_t* src) {
lwrb_sz_t len_to_copy, len_to_copy_orig, src_full, dest_free;
if (!BUF_IS_VALID(dest) || !BUF_IS_VALID(src)) {
return 0;
}
src_full = lwrb_get_full(src);
dest_free = lwrb_get_free(dest);
len_to_copy = BUF_MIN(src_full, dest_free);
len_to_copy_orig = len_to_copy;
/* Calculations for available length to copy is done above.
We safely assume operations inside loop will properly complete. */
while (len_to_copy > 0) {
lwrb_sz_t max_seq_read, max_seq_write, op_len;
const uint8_t* d_src;
uint8_t* d_dst;
/* Calculate data */
max_seq_read = lwrb_get_linear_block_read_length(src);
max_seq_write = lwrb_get_linear_block_write_length(dest);
op_len = BUF_MIN(max_seq_read, max_seq_write);
op_len = BUF_MIN(len_to_copy, op_len);
/* Get addresses */
d_src = lwrb_get_linear_block_read_address(src);
d_dst = lwrb_get_linear_block_write_address(dest);
/* Byte by byte copy */
for (lwrb_sz_t i = 0; i < op_len; ++i) {
*d_dst++ = *d_src++;
}
lwrb_advance(dest, op_len);
lwrb_skip(src, op_len);
len_to_copy -= op_len;
if (op_len == 0) {
/* Hard error... */
return 0;
}
}
return len_to_copy_orig;
}
#endif /* defined(LWRB_DEV) */