Added an unget() method to the sequential stream interface.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16240 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2023-04-28 12:39:18 +00:00
parent 06a115b1bb
commit 298b40a1a6
17 changed files with 1400 additions and 18 deletions

View File

@ -100,6 +100,7 @@ include $(CHIBIOS)/os/license/license.mk
include $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32g4xx.mk
# Common files.
include $(CHIBIOS)/os/common/oop/oop.mk
include $(CHIBIOS)/os/common/lib/lib.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/xhal/hal.mk
include $(CHIBIOS)/os/xhal/ports/STM32/STM32G4xx/platform.mk

View File

@ -0,0 +1,15 @@
sourceRoot: ../../../../tools/ftl/processors/ccode
outputRoot: ..
dataRoot: .
freemarkerLinks: {
ftllibs: ../../../../tools/ftl/libs
}
data : {
xml:xml (
modules.xml
{
}
)
}

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.chibios.org/xml/schema/ccode/modules.xsd"
name="memstreams" descr="Memory Streams" editcode="false">
<brief>Memory streams class.</brief>
<imports>
<import>oop_base_object.xml</import>
<import>oop_sequential_stream.xml</import>
</imports>
<public>
<includes>
<include style="angular">string.h</include>
<include style="regular">oop_base_object.h</include>
<include style="regular">oop_sequential_stream.h</include>
</includes>
<types>
<class type="regular" name="memory_stream"
namespace="memstm" ancestorname="base_object"
descr="memory stream">
<brief>Memory streams class.</brief>
<details><![CDATA[This class allows to manage a memory buffer using
a stream interface.]]></details>
<implements>
<if name="sequential_stream">
<method shortname="write">
<implementation><![CDATA[
if (self->size - self->eos < n) {
n = self->size - self->eos;
}
memcpy(self->buffer + self->eos, bp, n);
self->eos += n;
return n;]]></implementation>
</method>
<method shortname="read">
<implementation><![CDATA[
if (self->eos - self->offset < n) {
n = self->eos - self->offset;
}
memcpy(bp, self->buffer + self->offset, n);
self->offset += n;
return n;]]></implementation>
</method>
<method shortname="put">
<implementation><![CDATA[
if (self->size - self->eos <= 0U) {
return STM_RESET;
}
*(self->buffer + self->eos) = b;
self->eos++;
return STM_OK;]]></implementation>
</method>
<method shortname="get">
<implementation><![CDATA[
uint8_t b;
if (self->eos - self->offset <= 0U) {
return STM_RESET;
}
b = *(self->buffer + self->offset);
self->offset++;
return b;]]></implementation>
</method>
<method shortname="unget">
<implementation><![CDATA[
if ((b == STM_RESET) || (self->offset <= 0U)) {
return STM_RESET;
}
self->offset--;
*(self->buffer + self->offset) = (uint8_t)b;
return STM_OK;]]></implementation>
</method>
</if>
</implements>
<fields>
<field name="buffer" ctype="uint8_t$I*">
<brief>Pointer to the memory buffer.</brief>
</field>
<field name="size" ctype="size_t">
<brief>Size of the memory buffer.</brief>
</field>
<field name="eos" ctype="size_t">
<brief>Current end of the stream.</brief>
</field>
<field name="offset" ctype="size_t">
<brief>Current read offset.</brief>
</field>
</fields>
<methods>
<objinit callsuper="true">
<param name="buffer" ctype="uint8_t *">Pointer to the memory
buffer for the memory stream.
</param>
<param name="size" ctype="size_t">Size of the memory stream
buffer.</param>
<param name="eos" ctype="size_t"><![CDATA[Initial End Of Stream
offset. Normally you need to put this to zero for RAM buffers
or equal to @p size for ROM streams.]]></param>
<implementation><![CDATA[
self->buffer = buffer;
self->size = size;
self->eos = eos;
self->offset = 0U;]]></implementation>
</objinit>
<dispose>
<implementation><![CDATA[ ]]></implementation>
</dispose>
</methods>
</class>
</types>
</public>
<private>
</private>
</module>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE doc [
<!ENTITY memstreams SYSTEM "memstreams.xml">
<!ENTITY oop_base_interface SYSTEM "oop_base_interface.xml">
<!ENTITY oop_referenced_object SYSTEM "oop_referenced_object.xml">
<!ENTITY oop_synchronized_object SYSTEM "oop_synchronized_object.xml">
<!ENTITY oop_sequential_stream SYSTEM "oop_sequential_stream.xml">
]>
<!-- Class/interfaces definitions -->
<instance
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.chibios.org/xml/schema/ccode/modules.xsd">
<paths>
<path>../../oop/codegen</path>
</paths>
<modules>
&memstreams;
</modules>
</instance>

View File

@ -0,0 +1,52 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file chprintf.h
* @brief Mini printf-like functionality.
*
* @addtogroup HAL_CHPRINTF
* @{
*/
#ifndef CHPRINTF_H
#define CHPRINTF_H
#include <stdarg.h>
#include "oop_sequential_stream.h"
/**
* @brief Float type support.
*/
#if !defined(CHPRINTF_USE_FLOAT) || defined(__DOXYGEN__)
#define CHPRINTF_USE_FLOAT FALSE
#endif
#ifdef __cplusplus
extern "C" {
#endif
int chvprintf(sequential_stream_i *chp, const char *fmt, va_list ap);
int chprintf(sequential_stream_i *chp, const char *fmt, ...);
int chsnprintf(char *str, size_t size, const char *fmt, ...);
int chvsnprintf(char *str, size_t size, const char *fmt, va_list ap);
#ifdef __cplusplus
}
#endif
#endif /* CHPRINTF_H */
/** @} */

View File

@ -0,0 +1,128 @@
/*
ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
This file is part of ChibiOS.
ChibiOS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
ChibiOS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file errcodes.h
* @brief Errors handling header file.
*
* @addtogroup UTILS_ERRCODES
* @{
*/
#ifndef ERRCODES_H
#define ERRCODES_H
#include <errno.h>
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/**
* @name Error codes
* @{
*/
#define CH_RET_SUCCESS (int)MSG_OK /* Success */
#define CH_RET_TIMEOUT (int)MSG_TIMEOUT /* Timeout */
#define CH_RET_INNER_ERROR (int)-3 /* Unexpected condition */
/** @} */
/**
* @name Extra error codes mapped on Posix errors
* @{
*/
#define CH_RET_ENOENT CH_ENCODE_ERROR(ENOENT) /* No such file or directory */
#define CH_RET_EIO CH_ENCODE_ERROR(EIO) /* I/O error */
#define CH_RET_EBADF CH_ENCODE_ERROR(EBADF) /* Bad file number */
#define CH_RET_ENOMEM CH_ENCODE_ERROR(ENOMEM) /* Not enough space */
#define CH_RET_EACCES CH_ENCODE_ERROR(EACCES) /* Permission denied */
#define CH_RET_EFAULT CH_ENCODE_ERROR(EACCES) /* Bad address */
#define CH_RET_EEXIST CH_ENCODE_ERROR(EEXIST) /* File exists */
#define CH_RET_ENOTDIR CH_ENCODE_ERROR(ENOTDIR) /* Not a directory */
#define CH_RET_EISDIR CH_ENCODE_ERROR(EISDIR) /* Is a directory */
#define CH_RET_EINVAL CH_ENCODE_ERROR(EINVAL) /* Invalid argument */
#define CH_RET_EMFILE CH_ENCODE_ERROR(EMFILE) /* Too many open files in process */
#define CH_RET_ENFILE CH_ENCODE_ERROR(ENFILE) /* Too many open files in system */
#define CH_RET_EFBIG CH_ENCODE_ERROR(EFBIG) /* File too large */
#define CH_RET_ENOSPC CH_ENCODE_ERROR(ENOSPC) /* No space left on device */
#define CH_RET_ESPIPE CH_ENCODE_ERROR(ESPIPE) /* Illegal seek */
#define CH_RET_EROFS CH_ENCODE_ERROR(EROFS) /* Read-only file system */
#define CH_RET_ERANGE CH_ENCODE_ERROR(ERANGE) /* Result too large */
#define CH_RET_ENAMETOOLONG CH_ENCODE_ERROR(ENAMETOOLONG)/* File or path name too long */
#define CH_RET_ENOSYS CH_ENCODE_ERROR(ENOSYS) /* Syscall not implemented */
#define CH_RET_EOVERFLOW CH_ENCODE_ERROR(EOVERFLOW) /* File offset overflow */
#define CH_RET_ENOEXEC CH_ENCODE_ERROR(ENOEXEC) /* Invalid executable */
#define CH_RET_EXDEV CH_ENCODE_ERROR(EXDEV) /* Not same volume */
/** @} */
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/**
* @name Errors handling macros
* @{
*/
#define CH_ERRORS_MASK (int)0xFF
#define CH_ENCODE_ERROR(posixerr) (~CH_ERRORS_MASK | (int)(posixerr))
#define CH_DECODE_ERROR(err) ((int)(err) & CH_ERRORS_MASK)
#define CH_RET_IS_ERROR(x) (((int)(x) & ~CH_ERRORS_MASK) == ~CH_ERRORS_MASK)
#define CH_BREAK_ON_ERROR(err) \
if (CH_RET_IS_ERROR(err)) break
#define CH_RETURN_ON_ERROR(err) do { \
int __ret = (err); \
if (CH_RET_IS_ERROR(__ret)) { \
return __ret; \
} \
} while (false)
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
#endif /* ERRCODES_H */
/** @} */

View File

@ -0,0 +1,164 @@
/*
ChibiOS - Copyright (C) 2006..2023 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file memstreams.h
* @brief Generated Memory Streams header.
* @note This is a generated file, do not edit directly.
*
* @addtogroup MEMSTREAMS
* @brief Memory streams class.
* @{
*/
#ifndef MEMSTREAMS_H
#define MEMSTREAMS_H
#include <string.h>
#include "oop_base_object.h"
#include "oop_sequential_stream.h"
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Module macros. */
/*===========================================================================*/
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
/**
* @class memory_stream_c
* @extends base_object_c.
* @implements sequential_stream_i
*
* @brief Memory streams class.
* @details This class allows to manage a memory buffer using a stream
* interface.
*
* @name Class @p memory_stream_c structures
* @{
*/
/**
* @brief Type of a memory stream class.
*/
typedef struct memory_stream memory_stream_c;
/**
* @brief Class @p memory_stream_c virtual methods table.
*/
struct memory_stream_vmt {
/* From base_object_c.*/
void (*dispose)(void *ip);
/* From memory_stream_c.*/
};
/**
* @brief Structure representing a memory stream class.
*/
struct memory_stream {
/**
* @brief Virtual Methods Table.
*/
const struct memory_stream_vmt *vmt;
/**
* @brief Implemented interface @p sequential_stream_i.
*/
sequential_stream_i stm;
/**
* @brief Pointer to the memory buffer.
*/
uint8_t *buffer;
/**
* @brief Size of the memory buffer.
*/
size_t size;
/**
* @brief Current end of the stream.
*/
size_t eos;
/**
* @brief Current read offset.
*/
size_t offset;
};
/** @} */
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/* Methods of memory_stream_c.*/
void *__memstm_objinit_impl(void *ip, const void *vmt, uint8_t *buffer,
size_t size, size_t eos);
void __memstm_dispose_impl(void *ip);
#ifdef __cplusplus
}
#endif
/*===========================================================================*/
/* Module inline functions. */
/*===========================================================================*/
/**
* @name Default constructor of memory_stream_c
* @{
*/
/**
* @memberof memory_stream_c
*
* @brief Default initialization function of @p memory_stream_c.
*
* @param[out] self Pointer to a @p memory_stream_c instance to be
* initialized.
* @param buffer Pointer to the memory buffer for the memory
* stream.
* @param size Size of the memory stream buffer.
* @param eos Initial End Of Stream offset. Normally you need
* to put this to zero for RAM buffers or equal to
* @p size for ROM streams.
* @return Pointer to the initialized object.
*
* @objinit
*/
CC_FORCE_INLINE
static inline memory_stream_c *memstmObjectInit(memory_stream_c *self,
uint8_t *buffer, size_t size,
size_t eos) {
extern const struct memory_stream_vmt __memory_stream_vmt;
return __memstm_objinit_impl(self, &__memory_stream_vmt, buffer, size, eos);
}
/** @} */
#endif /* MEMSTREAMS_H */
/** @} */

9
os/common/lib/lib.mk Normal file
View File

@ -0,0 +1,9 @@
# List of the ChibiOS common library modules.
CLIBSRC = ${CHIBIOS}/os/common/lib/src/memstreams.c \
${CHIBIOS}/os/common/lib/src/chprintf.c
CLIBINC = ${CHIBIOS}/os/common/lib/include
# Shared variables
ALLCSRC += $(CLIBSRC)
ALLINC += $(CLIBINC)

View File

@ -0,0 +1,470 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Concepts and parts of this file have been contributed by Fabio Utzig,
chvprintf() added by Brent Roman.
*/
/**
* @file chprintf.c
* @brief Mini printf-like functionality.
*
* @addtogroup HAL_CHPRINTF
* @details Mini printf-like functionality.
* @{
*/
#include "chprintf.h"
#include "memstreams.h"
#define MAX_FILLER 11
#define FLOAT_PRECISION 9
static char *long_to_string_with_divisor(char *p,
long num,
unsigned radix,
long divisor) {
int i;
char *q;
long l, ll;
l = num;
if (divisor == 0) {
ll = num;
} else {
ll = divisor;
}
q = p + MAX_FILLER;
do {
i = (int)(l % radix);
i += '0';
if (i > '9') {
i += 'A' - '0' - 10;
}
*--q = i;
l /= radix;
} while ((ll /= radix) != 0);
i = (int)(p + MAX_FILLER - q);
do
*p++ = *q++;
while (--i);
return p;
}
static char *ch_ltoa(char *p, long num, unsigned radix) {
return long_to_string_with_divisor(p, num, radix, 0);
}
#if CHPRINTF_USE_FLOAT
static const long pow10[FLOAT_PRECISION] = {
10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
};
static char *ftoa(char *p, double num, unsigned long precision) {
long l;
if ((precision == 0) || (precision > FLOAT_PRECISION)) {
precision = FLOAT_PRECISION;
}
precision = pow10[precision - 1];
l = (long)num;
p = long_to_string_with_divisor(p, l, 10, 0);
*p++ = '.';
l = (long)((num - l) * precision);
return long_to_string_with_divisor(p, l, 10, precision / 10);
}
#endif
/**
* @brief System formatted output function.
* @details This function implements a minimal @p vprintf()-like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] stmp pointer to a @p sequential_stream_i interface
* @param[in] fmt formatting string
* @param[in] ap list of parameters
* @return The number of bytes that would have been
* written to @p chp if no stream error occurs
*
* @api
*/
int chvprintf(sequential_stream_i *stmp, const char *fmt, va_list ap) {
char *p, *s, c, filler;
int i, precision, width;
int n = 0;
bool is_long, left_align, do_sign;
long l;
#if CHPRINTF_USE_FLOAT
float f;
char tmpbuf[2*MAX_FILLER + 1];
#else
char tmpbuf[MAX_FILLER + 1];
#endif
while (true) {
c = *fmt++;
if (c == 0) {
return n;
}
if (c != '%') {
stmPut(stmp, (uint8_t)c);
n++;
continue;
}
p = tmpbuf;
s = tmpbuf;
/* Alignment mode.*/
left_align = false;
if (*fmt == '-') {
fmt++;
left_align = true;
}
/* Sign mode.*/
do_sign = false;
if (*fmt == '+') {
fmt++;
do_sign = true;
}
/* Filler mode.*/
filler = ' ';
if (*fmt == '0') {
fmt++;
filler = '0';
}
/* Width modifier.*/
if ( *fmt == '*') {
width = va_arg(ap, int);
++fmt;
c = *fmt++;
}
else {
width = 0;
while (true) {
c = *fmt++;
if (c == 0) {
return n;
}
if (c >= '0' && c <= '9') {
c -= '0';
width = width * 10 + c;
}
else {
break;
}
}
}
/* Precision modifier.*/
precision = 0;
if (c == '.') {
c = *fmt++;
if (c == 0) {
return n;
}
if (c == '*') {
precision = va_arg(ap, int);
c = *fmt++;
}
else {
while (c >= '0' && c <= '9') {
c -= '0';
precision = precision * 10 + c;
c = *fmt++;
if (c == 0) {
return n;
}
}
}
}
/* Long modifier.*/
if (c == 'l' || c == 'L') {
is_long = true;
c = *fmt++;
if (c == 0) {
return n;
}
}
else {
is_long = (c >= 'A') && (c <= 'Z');
}
/* Command decoding.*/
switch (c) {
case 'c':
filler = ' ';
*p++ = va_arg(ap, int);
break;
case 's':
filler = ' ';
if ((s = va_arg(ap, char *)) == 0) {
s = "(null)";
}
if (precision == 0) {
precision = 32767;
}
for (p = s; *p && (--precision >= 0); p++)
;
break;
case 'D':
case 'd':
case 'I':
case 'i':
if (is_long) {
l = va_arg(ap, long);
}
else {
l = va_arg(ap, int);
}
if (l < 0) {
*p++ = '-';
l = -l;
}
else
if (do_sign) {
*p++ = '+';
}
p = ch_ltoa(p, l, 10);
break;
#if CHPRINTF_USE_FLOAT
case 'f':
f = (float) va_arg(ap, double);
if (f < 0) {
*p++ = '-';
f = -f;
}
else {
if (do_sign) {
*p++ = '+';
}
}
p = ftoa(p, f, precision);
break;
#endif
case 'X':
case 'x':
case 'P':
case 'p':
c = 16;
goto unsigned_common;
case 'U':
case 'u':
c = 10;
goto unsigned_common;
case 'O':
case 'o':
c = 8;
unsigned_common:
if (is_long) {
l = va_arg(ap, unsigned long);
}
else {
l = va_arg(ap, unsigned int);
}
p = ch_ltoa(p, l, c);
break;
default:
*p++ = c;
break;
}
i = (int)(p - s);
if ((width -= i) < 0) {
width = 0;
}
if (left_align == false) {
width = -width;
}
if (width < 0) {
if ((*s == '-' || *s == '+') && filler == '0') {
stmPut(stmp, (uint8_t)*s++);
n++;
i--;
}
do {
stmPut(stmp, (uint8_t)filler);
n++;
} while (++width != 0);
}
while (--i >= 0) {
stmPut(stmp, (uint8_t)*s++);
n++;
}
while (width) {
stmPut(stmp, (uint8_t)filler);
n++;
width--;
}
}
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p printf() like functionality
* with output on a @p BaseSequentialStream.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
*
* @param[in] stmp pointer to a @p sequential_stream_i interface
* @param[in] fmt formatting string
* @return The number of bytes that would have been
* written to @p chp if no stream error occurs
*
* @api
*/
int chprintf(sequential_stream_i *stmp, const char *fmt, ...) {
va_list ap;
int formatted_bytes;
va_start(ap, fmt);
formatted_bytes = chvprintf(stmp, fmt, ap);
va_end(ap);
return formatted_bytes;
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p snprintf()-like functionality.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
* @post @p str is NUL-terminated, unless @p size is 0.
*
* @param[in] str pointer to a buffer
* @param[in] size maximum size of the buffer
* @param[in] fmt formatting string
* @return The number of characters (excluding the
* terminating NUL byte) that would have been
* stored in @p str if there was room.
*
* @api
*/
int chsnprintf(char *str, size_t size, const char *fmt, ...) {
va_list ap;
int retval;
/* Performing the print operation.*/
va_start(ap, fmt);
retval = chvsnprintf(str, size, fmt, ap);
va_end(ap);
/* Return number of bytes that would have been written.*/
return retval;
}
/**
* @brief System formatted output function.
* @details This function implements a minimal @p vsnprintf()-like functionality.
* The general parameters format is: %[-][width|*][.precision|*][l|L]p.
* The following parameter types (p) are supported:
* - <b>x</b> hexadecimal integer.
* - <b>X</b> hexadecimal long.
* - <b>o</b> octal integer.
* - <b>O</b> octal long.
* - <b>d</b> decimal signed integer.
* - <b>D</b> decimal signed long.
* - <b>u</b> decimal unsigned integer.
* - <b>U</b> decimal unsigned long.
* - <b>c</b> character.
* - <b>s</b> string.
* .
* @post @p str is NUL-terminated, unless @p size is 0.
*
* @param[in] str pointer to a buffer
* @param[in] size maximum size of the buffer
* @param[in] fmt formatting string
* @param[in] ap list of parameters
* @return The number of characters (excluding the
* terminating NUL byte) that would have been
* stored in @p str if there was room.
*
* @api
*/
int chvsnprintf(char *str, size_t size, const char *fmt, va_list ap) {
memory_stream_c ms;
size_t size_wo_nul;
int retval;
if (size > 0)
size_wo_nul = size - 1;
else
size_wo_nul = 0;
/* Memory stream object to be used as a string writer, reserving one
byte for the final zero.*/
memstmObjectInit(&ms, (uint8_t *)str, size_wo_nul, 0U);
/* Performing the print operation using the common code.*/
retval = chvprintf(oopGetIf(&ms, stm), fmt, ap);
/* Terminate with a zero, unless size==0.*/
if (ms.eos < size) {
str[ms.eos] = 0;
}
/* Return number of bytes that would have been written.*/
return retval;
}
/** @} */

View File

@ -0,0 +1,272 @@
/*
ChibiOS - Copyright (C) 2006..2023 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file memstreams.c
* @brief Generated Memory Streams source.
* @note This is a generated file, do not edit directly.
*
* @addtogroup MEMSTREAMS
* @{
*/
#include "memstreams.h"
/*===========================================================================*/
/* Module local definitions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local macros. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local types. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Module local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module exported functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Module class "memory_stream_c" methods. */
/*===========================================================================*/
/**
* @name Interfaces implementation of memory_stream_c
* @{
*/
/**
* @memberof memory_stream_c
* @private
*
* @brief Implementation of interface method @p stmWrite().
*
* @param[in,out] ip Pointer to the @p sequential_stream_i class
* interface.
* @param[in] bp Pointer to the data buffer.
* @param[in] n The maximum amount of data to be transferred.
* @return The number of bytes transferred. The returned
* value can be less than the specified number of
* bytes if an end-of-file condition has been met.
*/
static size_t __memstm_stm_write_impl(void *ip, const uint8_t *bp, size_t n) {
memory_stream_c *self = oopIfGetOwner(memory_stream_c, ip);
if (self->size - self->eos < n) {
n = self->size - self->eos;
}
memcpy(self->buffer + self->eos, bp, n);
self->eos += n;
return n;
}
/**
* @memberof memory_stream_c
* @private
*
* @brief Implementation of interface method @p stmRead().
*
* @param[in,out] ip Pointer to the @p sequential_stream_i class
* interface.
* @param[out] bp Pointer to the data buffer.
* @param[in] n The maximum amount of data to be transferred.
* @return The number of bytes transferred. The returned
* value can be less than the specified number of
* bytes if an end-of-file condition has been met.
*/
static size_t __memstm_stm_read_impl(void *ip, uint8_t *bp, size_t n) {
memory_stream_c *self = oopIfGetOwner(memory_stream_c, ip);
if (self->eos - self->offset < n) {
n = self->eos - self->offset;
}
memcpy(bp, self->buffer + self->offset, n);
self->offset += n;
return n;
}
/**
* @memberof memory_stream_c
* @private
*
* @brief Implementation of interface method @p stmPut().
*
* @param[in,out] ip Pointer to the @p sequential_stream_i class
* interface.
* @param[in] b The byte value to be written to the stream.
* @return The operation status.
*/
static int __memstm_stm_put_impl(void *ip, uint8_t b) {
memory_stream_c *self = oopIfGetOwner(memory_stream_c, ip);
if (self->size - self->eos <= 0U) {
return STM_RESET;
}
*(self->buffer + self->eos) = b;
self->eos++;
return STM_OK;
}
/**
* @memberof memory_stream_c
* @private
*
* @brief Implementation of interface method @p stmGet().
*
* @param[in,out] ip Pointer to the @p sequential_stream_i class
* interface.
* @return A byte value from the stream.
*/
static int __memstm_stm_get_impl(void *ip) {
memory_stream_c *self = oopIfGetOwner(memory_stream_c, ip);
uint8_t b;
if (self->eos - self->offset <= 0U) {
return STM_RESET;
}
b = *(self->buffer + self->offset);
self->offset++;
return b;
}
/**
* @memberof memory_stream_c
* @private
*
* @brief Implementation of interface method @p stmUnget().
*
* @param[in,out] ip Pointer to the @p sequential_stream_i class
* interface.
* @param[in] b The byte value to be pushed back to the stream.
* @return The operation status.
*/
static int __memstm_stm_unget_impl(void *ip, int b) {
memory_stream_c *self = oopIfGetOwner(memory_stream_c, ip);
if ((b == STM_RESET) || (self->offset <= 0U)) {
return STM_RESET;
}
self->offset--;
*(self->buffer + self->offset) = (uint8_t)b;
return STM_OK;
}
/** @} */
/**
* @name Methods implementations of memory_stream_c
* @{
*/
/**
* @memberof memory_stream_c
* @protected
*
* @brief Implementation of object creation.
* @note This function is meant to be used by derived classes.
*
* @param[out] ip Pointer to a @p memory_stream_c instance to be
* initialized.
* @param[in] vmt VMT pointer for the new object.
* @param buffer Pointer to the memory buffer for the memory
* stream.
* @param size Size of the memory stream buffer.
* @param eos Initial End Of Stream offset. Normally you need
* to put this to zero for RAM buffers or equal to
* @p size for ROM streams.
* @return A new reference to the object.
*/
void *__memstm_objinit_impl(void *ip, const void *vmt, uint8_t *buffer,
size_t size, size_t eos) {
memory_stream_c *self = (memory_stream_c *)ip;
/* Initialization of the ancestors-defined parts.*/
__bo_objinit_impl(self, vmt);
/* Initialization of interface sequential_stream_i.*/
{
static const struct sequential_stream_vmt memstm_stm_vmt = {
.instance_offset = offsetof(memory_stream_c, stm),
.write = __memstm_stm_write_impl,
.read = __memstm_stm_read_impl,
.put = __memstm_stm_put_impl,
.get = __memstm_stm_get_impl,
.unget = __memstm_stm_unget_impl
};
oopIfObjectInit(&self->stm, &memstm_stm_vmt);
}
/* Initialization code.*/
self->buffer = buffer;
self->size = size;
self->eos = eos;
self->offset = 0U;
return self;
}
/**
* @memberof memory_stream_c
* @protected
*
* @brief Implementation of object finalization.
* @note This function is meant to be used by derived classes.
*
* @param[in,out] ip Pointer to a @p memory_stream_c instance to be
* disposed.
*/
void __memstm_dispose_impl(void *ip) {
memory_stream_c *self = (memory_stream_c *)ip;
/* No finalization code.*/
(void)self;
/* Finalization of the ancestors-defined parts.*/
__bo_dispose_impl(self);
}
/** @} */
/**
* @brief VMT structure of memory stream class.
* @note It is public because accessed by the inlined constructor.
*/
const struct memory_stream_vmt __memory_stream_vmt = {
.dispose = __memstm_dispose_impl
};
/** @} */

View File

@ -12,9 +12,18 @@
</includes>
<definitions_early>
<group description="Streams return codes">
<define name="STM_OK" value="MSG_OK" />
<define name="STM_TIMEOUT" value="MSG_TIMEOUT" />
<define name="STM_RESET" value="MSG_RESET" />
<define name="STM_OK" value="0" >
<brief>Returned code for operation successful.</brief>
<note>It is an alias of @p MSG_OK.</note>
</define>
<define name="STM_TIMEOUT" value="-1">
<brief>Returned code for operation timeout.</brief>
<note>It is an alias of @p MSG_TIMEOUT.</note>
</define>
<define name="STM_RESET" value="-2">
<brief>Returned code for stream reset or End-of-File.</brief>
<note>It is an alias of @p MSG_RESET.</note>
</define>
</group>
<condition check="defined(OOP_USE_LEGACY)">
<group description="Legacy interface method names">
@ -72,7 +81,7 @@
value can be less than the specified number of bytes
if an end-of-file condition has been met.]]></return>
</method>
<method name="stmPut" shortname="put" ctype="msg_t">
<method name="stmPut" shortname="put" ctype="int">
<brief>Sequential Stream blocking byte write.</brief>
<details><![CDATA[This function writes a byte value to a stream.
If the stream is not ready to accept data then the calling
@ -81,13 +90,29 @@
be written to the stream.
</param>
<return>The operation status.</return>
<retval value="STM_OK">If the byte has been written.</retval>
<retval value="STM_RESET">If an end-of-file condition has been met.</retval>
</method>
<method name="stmGet" shortname="get" ctype="msg_t">
<method name="stmGet" shortname="get" ctype="int">
<brief>Sequential Stream blocking byte read.</brief>
<details><![CDATA[This function reads a byte value from a stream.
If the data is not available then the calling thread is
suspended.]]></details>
<return>A byte value from the stream.</return>
<retval value="STM_RESET">If an end-of-file condition has been met.</retval>
</method>
<method name="stmUnget" shortname="unget" ctype="int">
<brief>Pushes back a byte into the stream.</brief>
<details><![CDATA[The specified byte is pushed back into the
stream.]]></details>
<note><![CDATA[Implementing classes may have limited push-back buffer
capacity or not be able to push-back at all.]]></note>
<param name="b" ctype="int" dir="in">The byte value to
be pushed back to the stream.
</param>
<return>The operation status.</return>
<retval value="STM_OK">If the byte has been pushed back.</retval>
<retval value="STM_RESET">If there is no push-back capacity left.</retval>
</method>
</methods>
</interface>

View File

@ -37,9 +37,23 @@
* @name Streams return codes
* @{
*/
#define STM_OK MSG_OK
#define STM_TIMEOUT MSG_TIMEOUT
#define STM_RESET MSG_RESET
/**
* @brief Returned code for operation successful.
* @note It is an alias of @p MSG_OK.
*/
#define STM_OK 0
/**
* @brief Returned code for operation timeout.
* @note It is an alias of @p MSG_TIMEOUT.
*/
#define STM_TIMEOUT -1
/**
* @brief Returned code for stream reset or End-of-File.
* @note It is an alias of @p MSG_RESET.
*/
#define STM_RESET -2
/** @} */
#if (defined(OOP_USE_LEGACY)) || defined (__DOXYGEN__)
@ -102,8 +116,9 @@ struct sequential_stream_vmt {
/* From sequential_stream_i.*/
size_t (*write)(void *ip, const uint8_t *bp, size_t n);
size_t (*read)(void *ip, uint8_t *bp, size_t n);
msg_t (*put)(void *ip, uint8_t b);
msg_t (*get)(void *ip);
int (*put)(void *ip, uint8_t b);
int (*get)(void *ip);
int (*unget)(void *ip, int b);
};
/**
@ -196,9 +211,11 @@ static inline size_t stmRead(void *ip, uint8_t *bp, size_t n) {
* @param[in,out] ip Pointer to a @p sequential_stream_i instance.
* @param[in] b The byte value to be written to the stream.
* @return The operation status.
* @retval STM_OK If the byte has been written.
* @retval STM_RESET If an end-of-file condition has been met.
*/
CC_FORCE_INLINE
static inline msg_t stmPut(void *ip, uint8_t b) {
static inline int stmPut(void *ip, uint8_t b) {
sequential_stream_i *self = (sequential_stream_i *)ip;
return self->vmt->put(ip, b);
@ -214,13 +231,36 @@ static inline msg_t stmPut(void *ip, uint8_t b) {
*
* @param[in,out] ip Pointer to a @p sequential_stream_i instance.
* @return A byte value from the stream.
* @retval STM_RESET If an end-of-file condition has been met.
*/
CC_FORCE_INLINE
static inline msg_t stmGet(void *ip) {
static inline int stmGet(void *ip) {
sequential_stream_i *self = (sequential_stream_i *)ip;
return self->vmt->get(ip);
}
/**
* @memberof sequential_stream_i
* @public
*
* @brief Pushes back a byte into the stream.
* @details The specified byte is pushed back into the stream.
* @note Implementing classes may have limited push-back buffer capacity
* or not be able to push-back at all.
*
* @param[in,out] ip Pointer to a @p sequential_stream_i instance.
* @param[in] b The byte value to be pushed back to the stream.
* @return The operation status.
* @retval STM_OK If the byte has been pushed back.
* @retval STM_RESET If there is no push-back capacity left.
*/
CC_FORCE_INLINE
static inline int stmUnget(void *ip, int b) {
sequential_stream_i *self = (sequential_stream_i *)ip;
return self->vmt->unget(ip, b);
}
/** @} */
#endif /* OOP_SEQUENTIAL_STREAM_H */

View File

@ -36,6 +36,14 @@ return oqPutTimeout(&self->oqueue, b, TIME_INFINITE);]]></implementation>
return iqGetTimeout(&self->iqueue, TIME_INFINITE);]]></implementation>
</method>
<method shortname="unget">
<implementation><![CDATA[
(void)self;
(void)b;
return STM_RESET;]]></implementation>
</method>
<method shortname="writet">
<implementation><![CDATA[

View File

@ -462,6 +462,14 @@ if (msg != MSG_OK) {
}
return sioGetX(self);]]></implementation>
</method>
<method shortname="unget">
<implementation><![CDATA[
(void)self;
(void)b;
return STM_RESET;]]></implementation>
</method>
<method shortname="writet">
<implementation><![CDATA[

View File

@ -191,8 +191,9 @@ struct asynchronous_channel_vmt {
/* From sequential_stream_i.*/
size_t (*write)(void *ip, const uint8_t *bp, size_t n);
size_t (*read)(void *ip, uint8_t *bp, size_t n);
msg_t (*put)(void *ip, uint8_t b);
msg_t (*get)(void *ip);
int (*put)(void *ip, uint8_t b);
int (*get)(void *ip);
int (*unget)(void *ip, int b);
/* From asynchronous_channel_i.*/
size_t (*writet)(void *ip, const uint8_t *bp, size_t n, sysinterval_t timeout);
size_t (*readt)(void *ip, uint8_t *bp, size_t n, sysinterval_t timeout);

View File

@ -112,7 +112,7 @@ static size_t __bs_chn_read_impl(void *ip, uint8_t *bp, size_t n) {
* @param[in] b The byte value to be written to the stream.
* @return The operation status.
*/
static msg_t __bs_chn_put_impl(void *ip, uint8_t b) {
static int __bs_chn_put_impl(void *ip, uint8_t b) {
hal_buffered_serial_c *self = oopIfGetOwner(hal_buffered_serial_c, ip);
return oqPutTimeout(&self->oqueue, b, TIME_INFINITE);
@ -128,12 +128,32 @@ static msg_t __bs_chn_put_impl(void *ip, uint8_t b) {
* interface.
* @return A byte value from the stream.
*/
static msg_t __bs_chn_get_impl(void *ip) {
static int __bs_chn_get_impl(void *ip) {
hal_buffered_serial_c *self = oopIfGetOwner(hal_buffered_serial_c, ip);
return iqGetTimeout(&self->iqueue, TIME_INFINITE);
}
/**
* @memberof hal_buffered_serial_c
* @private
*
* @brief Implementation of interface method @p stmUnget().
*
* @param[in,out] ip Pointer to the @p asynchronous_channel_i class
* interface.
* @param[in] b The byte value to be pushed back to the stream.
* @return The operation status.
*/
static int __bs_chn_unget_impl(void *ip, int b) {
hal_buffered_serial_c *self = oopIfGetOwner(hal_buffered_serial_c, ip);
(void)self;
(void)b;
return STM_RESET;
}
/**
* @memberof hal_buffered_serial_c
* @private
@ -316,6 +336,7 @@ void *__bs_objinit_impl(void *ip, const void *vmt, uint8_t *ib, size_t ibsize,
.read = __bs_chn_read_impl,
.put = __bs_chn_put_impl,
.get = __bs_chn_get_impl,
.unget = __bs_chn_unget_impl,
.writet = __bs_chn_writet_impl,
.readt = __bs_chn_readt_impl,
.putt = __bs_chn_putt_impl,

View File

@ -171,7 +171,7 @@ static size_t __sio_chn_read_impl(void *ip, uint8_t *bp, size_t n) {
* @param[in] b The byte value to be written to the stream.
* @return The operation status.
*/
static msg_t __sio_chn_put_impl(void *ip, uint8_t b) {
static int __sio_chn_put_impl(void *ip, uint8_t b) {
hal_sio_driver_c *self = oopIfGetOwner(hal_sio_driver_c, ip);
msg_t msg;
@ -194,7 +194,7 @@ static msg_t __sio_chn_put_impl(void *ip, uint8_t b) {
* interface.
* @return A byte value from the stream.
*/
static msg_t __sio_chn_get_impl(void *ip) {
static int __sio_chn_get_impl(void *ip) {
hal_sio_driver_c *self = oopIfGetOwner(hal_sio_driver_c, ip);
msg_t msg;
@ -206,6 +206,26 @@ static msg_t __sio_chn_get_impl(void *ip) {
return sioGetX(self);
}
/**
* @memberof hal_sio_driver_c
* @private
*
* @brief Implementation of interface method @p stmUnget().
*
* @param[in,out] ip Pointer to the @p asynchronous_channel_i class
* interface.
* @param[in] b The byte value to be pushed back to the stream.
* @return The operation status.
*/
static int __sio_chn_unget_impl(void *ip, int b) {
hal_sio_driver_c *self = oopIfGetOwner(hal_sio_driver_c, ip);
(void)self;
(void)b;
return STM_RESET;
}
/**
* @memberof hal_sio_driver_c
* @private
@ -392,6 +412,7 @@ void *__sio_objinit_impl(void *ip, const void *vmt) {
.read = __sio_chn_read_impl,
.put = __sio_chn_put_impl,
.get = __sio_chn_get_impl,
.unget = __sio_chn_unget_impl,
.writet = __sio_chn_writet_impl,
.readt = __sio_chn_readt_impl,
.putt = __sio_chn_putt_impl,