git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16241 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
298b40a1a6
commit
831d2840df
|
@ -1,10 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE doc [
|
<!DOCTYPE doc [
|
||||||
<!ENTITY memstreams SYSTEM "memstreams.xml">
|
<!ENTITY memstreams SYSTEM "memstreams.xml">
|
||||||
<!ENTITY oop_base_interface SYSTEM "oop_base_interface.xml">
|
<!ENTITY nullstreams SYSTEM "nullstreams.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 -->
|
<!-- Class/interfaces definitions -->
|
||||||
<instance
|
<instance
|
||||||
|
@ -15,5 +12,6 @@
|
||||||
</paths>
|
</paths>
|
||||||
<modules>
|
<modules>
|
||||||
&memstreams;
|
&memstreams;
|
||||||
|
&nullstreams;
|
||||||
</modules>
|
</modules>
|
||||||
</instance>
|
</instance>
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?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="nullstreams" descr="Null Streams" editcode="false">
|
||||||
|
<brief>Null 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="null_stream"
|
||||||
|
namespace="nullstm" ancestorname="base_object"
|
||||||
|
descr="null stream">
|
||||||
|
<brief>Null streams class.</brief>
|
||||||
|
<details><![CDATA[This class implements a null stream.]]></details>
|
||||||
|
<implements>
|
||||||
|
<if name="sequential_stream">
|
||||||
|
<method shortname="write">
|
||||||
|
<implementation><![CDATA[
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)bp;
|
||||||
|
|
||||||
|
return n;]]></implementation>
|
||||||
|
</method>
|
||||||
|
<method shortname="read">
|
||||||
|
<implementation><![CDATA[
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)bp;
|
||||||
|
|
||||||
|
return n;]]></implementation>
|
||||||
|
</method>
|
||||||
|
<method shortname="put">
|
||||||
|
<implementation><![CDATA[
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)b;
|
||||||
|
|
||||||
|
return STM_OK;]]></implementation>
|
||||||
|
</method>
|
||||||
|
<method shortname="get">
|
||||||
|
<implementation><![CDATA[
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
|
||||||
|
return 4;]]></implementation>
|
||||||
|
</method>
|
||||||
|
<method shortname="unget">
|
||||||
|
<implementation><![CDATA[
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)b;
|
||||||
|
|
||||||
|
return STM_RESET;]]></implementation>
|
||||||
|
</method>
|
||||||
|
</if>
|
||||||
|
</implements>
|
||||||
|
<fields>
|
||||||
|
</fields>
|
||||||
|
<methods>
|
||||||
|
<objinit callsuper="true">
|
||||||
|
<implementation><![CDATA[ ]]></implementation>
|
||||||
|
</objinit>
|
||||||
|
<dispose>
|
||||||
|
<implementation><![CDATA[ ]]></implementation>
|
||||||
|
</dispose>
|
||||||
|
</methods>
|
||||||
|
</class>
|
||||||
|
</types>
|
||||||
|
</public>
|
||||||
|
<private>
|
||||||
|
</private>
|
||||||
|
</module>
|
|
@ -39,8 +39,8 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
int chvprintf(sequential_stream_i *chp, const char *fmt, va_list ap);
|
int chvprintf(sequential_stream_i *stmp, const char *fmt, va_list ap);
|
||||||
int chprintf(sequential_stream_i *chp, const char *fmt, ...);
|
int chprintf(sequential_stream_i *stmp, const char *fmt, ...);
|
||||||
int chsnprintf(char *str, size_t size, 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);
|
int chvsnprintf(char *str, size_t size, const char *fmt, va_list ap);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file was contributed by Alex Lewontin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file chscanf.h
|
||||||
|
* @brief Mini scanf-like functionality.
|
||||||
|
*
|
||||||
|
* @addtogroup HAL_CHSCANF
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CHSCANF_H
|
||||||
|
#define CHSCANF_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Float type support.
|
||||||
|
*/
|
||||||
|
#if !defined(CHSCANF_USE_FLOAT) || defined(__DOXYGEN__)
|
||||||
|
#define CHSCANF_USE_FLOAT FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CHSCANF_USE_FLOAT
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
int chvscanf(sequential_stream_i *stmp, const char *fmt, va_list ap);
|
||||||
|
int chscanf(sequential_stream_i *stmp, const char *fmt, ...);
|
||||||
|
int chsnscanf(char *str, size_t size, const char *fmt, ...);
|
||||||
|
int chvsnscanf(char *str, size_t size, const char *fmt, va_list ap);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CHSCANF_H */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
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 nullstreams.h
|
||||||
|
* @brief Generated Null Streams header.
|
||||||
|
* @note This is a generated file, do not edit directly.
|
||||||
|
*
|
||||||
|
* @addtogroup NULLSTREAMS
|
||||||
|
* @brief Null streams class.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NULLSTREAMS_H
|
||||||
|
#define NULLSTREAMS_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 null_stream_c
|
||||||
|
* @extends base_object_c.
|
||||||
|
* @implements sequential_stream_i
|
||||||
|
*
|
||||||
|
* @brief Null streams class.
|
||||||
|
* @details This class implements a null stream.
|
||||||
|
*
|
||||||
|
* @name Class @p null_stream_c structures
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of a null stream class.
|
||||||
|
*/
|
||||||
|
typedef struct null_stream null_stream_c;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class @p null_stream_c virtual methods table.
|
||||||
|
*/
|
||||||
|
struct null_stream_vmt {
|
||||||
|
/* From base_object_c.*/
|
||||||
|
void (*dispose)(void *ip);
|
||||||
|
/* From null_stream_c.*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure representing a null stream class.
|
||||||
|
*/
|
||||||
|
struct null_stream {
|
||||||
|
/**
|
||||||
|
* @brief Virtual Methods Table.
|
||||||
|
*/
|
||||||
|
const struct null_stream_vmt *vmt;
|
||||||
|
/**
|
||||||
|
* @brief Implemented interface @p sequential_stream_i.
|
||||||
|
*/
|
||||||
|
sequential_stream_i stm;
|
||||||
|
};
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* External declarations. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/* Methods of null_stream_c.*/
|
||||||
|
void *__nullstm_objinit_impl(void *ip, const void *vmt);
|
||||||
|
void __nullstm_dispose_impl(void *ip);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module inline functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Default constructor of null_stream_c
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @memberof null_stream_c
|
||||||
|
*
|
||||||
|
* @brief Default initialization function of @p null_stream_c.
|
||||||
|
*
|
||||||
|
* @param[out] self Pointer to a @p null_stream_c instance to be
|
||||||
|
* initialized.
|
||||||
|
* @return Pointer to the initialized object.
|
||||||
|
*
|
||||||
|
* @objinit
|
||||||
|
*/
|
||||||
|
CC_FORCE_INLINE
|
||||||
|
static inline null_stream_c *nullstmObjectInit(null_stream_c *self) {
|
||||||
|
extern const struct null_stream_vmt __null_stream_vmt;
|
||||||
|
|
||||||
|
return __nullstm_objinit_impl(self, &__null_stream_vmt);
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* NULLSTREAMS_H */
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -1,6 +1,8 @@
|
||||||
# List of the ChibiOS common library modules.
|
# List of the ChibiOS common library modules.
|
||||||
CLIBSRC = ${CHIBIOS}/os/common/lib/src/memstreams.c \
|
CLIBSRC = ${CHIBIOS}/os/common/lib/src/memstreams.c \
|
||||||
${CHIBIOS}/os/common/lib/src/chprintf.c
|
${CHIBIOS}/os/common/lib/src/nullstreams.c \
|
||||||
|
${CHIBIOS}/os/common/lib/src/chprintf.c \
|
||||||
|
${CHIBIOS}/os/common/lib/src/chscanf.c
|
||||||
|
|
||||||
CLIBINC = ${CHIBIOS}/os/common/lib/include
|
CLIBINC = ${CHIBIOS}/os/common/lib/include
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,795 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file was contributed by Alex Lewontin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file chscanf.c
|
||||||
|
* @brief Mini scanf-like functionality.
|
||||||
|
*
|
||||||
|
* @addtogroup HAL_CHSCANF
|
||||||
|
* @details Mini scanf-like functionality.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "hal.h"
|
||||||
|
#include "chscanf.h"
|
||||||
|
#include "memstreams.h"
|
||||||
|
|
||||||
|
static long sym_to_val(char sym, int base)
|
||||||
|
{
|
||||||
|
sym = tolower(sym);
|
||||||
|
if (sym <= '7' && sym >= '0') {
|
||||||
|
return sym - '0';
|
||||||
|
}
|
||||||
|
switch (base) {
|
||||||
|
case 16:
|
||||||
|
if (sym <= 'f' && sym >= 'a') {
|
||||||
|
return (sym - 'a' + 0xa);
|
||||||
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
case 10:
|
||||||
|
if (sym == '8') {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
if (sym == '9') {
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CHSCANF_USE_FLOAT
|
||||||
|
|
||||||
|
/* Custom mixed-type power function. The internal promotion of the result to a double
|
||||||
|
allows for a greater dynamic range than integral types. This function is mostly for
|
||||||
|
simplicity, to allow us to do floating point math without either requiring any
|
||||||
|
libc linkages, or actually having to write floating point algorithms ourselves */
|
||||||
|
static inline double ch_mpow(double x, unsigned long y)
|
||||||
|
{
|
||||||
|
double res = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (y & 1) {
|
||||||
|
res *= x;
|
||||||
|
}
|
||||||
|
x *= x;
|
||||||
|
} while (y >>= 1);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief System formatted input function.
|
||||||
|
* @details This function implements a minimal @p vscanf()-like functionality
|
||||||
|
* with input on a @p BaseSequentialStream.
|
||||||
|
* The general parameters format is: %[*][width][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] chp pointer to a @p BufferedStream implementing object
|
||||||
|
* @param[in] fmt formatting string
|
||||||
|
* @param[in] ap list of parameters
|
||||||
|
* @return The number parameters in ap that have been successfully
|
||||||
|
* filled. This does not conform to the standard in that if
|
||||||
|
* a failure (either matching or input) occurs before any
|
||||||
|
* parameters are assigned, the function will return 0.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
int chvscanf(sequential_stream_i *stmp, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
char f;
|
||||||
|
int c;
|
||||||
|
int width, base, i;
|
||||||
|
int n = 0;
|
||||||
|
void* buf;
|
||||||
|
bool is_long, is_signed, is_positive;
|
||||||
|
long vall, digit;
|
||||||
|
#if CHSCANF_USE_FLOAT
|
||||||
|
long exp;
|
||||||
|
double valf;
|
||||||
|
char exp_char;
|
||||||
|
int exp_base;
|
||||||
|
bool exp_is_positive, initial_digit;
|
||||||
|
char* match;
|
||||||
|
int fixed_point;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Peek the first character of the format string. If it is null,
|
||||||
|
we don't even need to take any input, just return 0 */
|
||||||
|
f = *fmt++;
|
||||||
|
if (f == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, get the first character from the input stream before we loop for the first time
|
||||||
|
(no peek function for the stream means an extra character is taken out every iteration of the
|
||||||
|
loop, so each loop iteration uses the value of c from the last one. However, the first iteration
|
||||||
|
has no value to work with, so we initialize it here) */
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
while (c != STM_RESET && f != 0) {
|
||||||
|
|
||||||
|
/* There are 3 options for f:
|
||||||
|
- whitespace (take and discard as much contiguous whitespace as possible)
|
||||||
|
- a non-whitespace, non-control sequence character (must 1:1 match)
|
||||||
|
- a %, which indicates the beginning of a control sequence
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (isspace(f)) {
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f != '%') {
|
||||||
|
if (f != c) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* So we have a formatting token... probably */
|
||||||
|
f = *fmt++;
|
||||||
|
/* Special case: a %% is equivalent to a '%' literal */
|
||||||
|
if (f == '%') {
|
||||||
|
if (f != c) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f == '*') {
|
||||||
|
buf = NULL;
|
||||||
|
f = *fmt++;
|
||||||
|
} else {
|
||||||
|
buf = va_arg(ap, void*);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the optional width specifier */
|
||||||
|
width = 0;
|
||||||
|
while (isdigit(f)) {
|
||||||
|
width = (width * 10) + (f - '0');
|
||||||
|
f = *fmt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!width) {
|
||||||
|
width = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the optional length specifier */
|
||||||
|
if (f == 'l' || f == 'L') {
|
||||||
|
is_long = true;
|
||||||
|
f = *fmt++;
|
||||||
|
} else {
|
||||||
|
is_long = isupper(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_positive = true;
|
||||||
|
is_signed = true;
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
switch (f) {
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
/* Not supporting wchar_t, is_long is just ignored */
|
||||||
|
if (width == 0) {
|
||||||
|
width = 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < width; ++i) {
|
||||||
|
if (buf) {
|
||||||
|
((char*)buf)[i] = c;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (c == STM_RESET) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++n;
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
/* S specifier discards leading whitespace */
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (c == STM_RESET) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Not supporting wchar_t, is_long is just ignored */
|
||||||
|
if (width == 0) {
|
||||||
|
width = -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < width; ++i) {
|
||||||
|
|
||||||
|
if (isspace(c)) {
|
||||||
|
if (buf) {
|
||||||
|
((char*)buf)[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf) {
|
||||||
|
((char*)buf)[i] = c;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (c == STM_RESET) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width != -1) {
|
||||||
|
if (buf) {
|
||||||
|
((char*)buf)[width] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++n;
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#if CHSCANF_USE_FLOAT
|
||||||
|
case 'f':
|
||||||
|
valf = -1;
|
||||||
|
exp_char = 'e';
|
||||||
|
exp_base = 10;
|
||||||
|
fixed_point = 0;
|
||||||
|
initial_digit = false;
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Special cases: a float can be INF(INITY) or NAN. As a note about this behavior:
|
||||||
|
this consumes "the longest sequence of input characters which does not exceed any
|
||||||
|
specified field width and which is, or is a prefix of, a matching input sequence" (from
|
||||||
|
the C99 standard). Therefore, if a '%f' format token gets the input 'INFINITxyx',
|
||||||
|
it will consume the 'INFINIT', leaving 'xyz' in the stream. Similarly, if it gets
|
||||||
|
'NAxyz', it will consume the 'NA', leaving 'xyz' in the stream.
|
||||||
|
|
||||||
|
Given that it seems a little odd to accept a short version and a long version, but not
|
||||||
|
a version in between that contains the short version but isn't long enough to be the
|
||||||
|
long version, This implementation is fairly permissive, and will accept anything from
|
||||||
|
'INF' to 'INFINITY', case insensative, (e.g. 'INF', 'INfiN', 'INFit', or 'infinity')
|
||||||
|
as a valid token meaning INF. It will not, however, accept less than 'INF' or 'NAN' as
|
||||||
|
a valid token (so the above example 'NAxyz' would consume the 'NA', but not recognize it
|
||||||
|
as signifying NaN)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tolower(c) == 'n') {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
match = "an";
|
||||||
|
while (*match != 0) {
|
||||||
|
if (*match != tolower(c)) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
if (--width == 0) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
++match;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
valf = NAN;
|
||||||
|
goto float_common;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tolower(c) == 'i') {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
match = "nf";
|
||||||
|
while (*match != 0) {
|
||||||
|
if (*match != tolower(c)) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
++match;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (--width == 0) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
valf = INFINITY;
|
||||||
|
|
||||||
|
match = "inity";
|
||||||
|
while (*match != 0) {
|
||||||
|
if (*match != tolower(c)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++match;
|
||||||
|
if (--width == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto float_common;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '0') {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (--width == 0) {
|
||||||
|
valf = 0;
|
||||||
|
goto float_common;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 'x' || c == 'X') {
|
||||||
|
base = 16;
|
||||||
|
exp_char = 'p';
|
||||||
|
exp_base = 2;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (--width == 0) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
valf = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sym_to_val(c, base) != -1) {
|
||||||
|
valf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (width--) {
|
||||||
|
digit = sym_to_val(c, base);
|
||||||
|
if (digit == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
valf = (valf * base) + (double)digit;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '.') {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
while (width--) {
|
||||||
|
digit = sym_to_val(c, base);
|
||||||
|
if (digit == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (valf == -1) {
|
||||||
|
valf = 0;
|
||||||
|
}
|
||||||
|
valf = (valf * base) + (double)digit;
|
||||||
|
++fixed_point;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valf == -1.0) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
valf = valf / ch_mpow(base, fixed_point);
|
||||||
|
|
||||||
|
if (tolower(c) == exp_char) {
|
||||||
|
if (width-- == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
exp_is_positive = true;
|
||||||
|
exp = 0;
|
||||||
|
|
||||||
|
if (c == '+') {
|
||||||
|
if (width-- == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (width-- == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
exp_is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
"When parsing an incomplete floating-point value that ends in the exponent with no digits,
|
||||||
|
such as parsing "100er" with the conversion specifier %f, the sequence "100e" (the longest
|
||||||
|
prefix of a possibly valid floating-point number) is consumed, resulting in a matching
|
||||||
|
error (the consumed sequence cannot be converted to a floating-point number), with "r"
|
||||||
|
remaining." (https://en.cppreference.com/w/c/io/fscanf)
|
||||||
|
*/
|
||||||
|
digit = sym_to_val(c, 10);
|
||||||
|
if (digit == -1) {
|
||||||
|
stmUnget(chp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
while (width--) {
|
||||||
|
/* Even if the significand was hex, the exponent is decimal */
|
||||||
|
digit = sym_to_val(c, 10);
|
||||||
|
if (digit == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exp = (exp * 10) + digit;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
if (exp_is_positive) {
|
||||||
|
valf = valf * (double)ch_mpow(exp_base, exp);
|
||||||
|
} else {
|
||||||
|
valf = valf / (double)ch_mpow(exp_base, exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float_common:
|
||||||
|
if (!is_positive) {
|
||||||
|
valf = -1 * valf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf) {
|
||||||
|
if (is_long) {
|
||||||
|
*(double*)buf = valf;
|
||||||
|
} else {
|
||||||
|
*(float*)buf = valf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++n;
|
||||||
|
f = *fmt++;
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'I':
|
||||||
|
/* I specifier discards leading whitespace */
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
/* The char might be +, might be -, might be 0, or might be something else */
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '0') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return ++n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (c == 'x' || c == 'X') {
|
||||||
|
base = 16;
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
base = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
is_signed = false;
|
||||||
|
base = 16;
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
if (c == '0') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return ++n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
if (c == 'x' || c == 'X') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
case 'u':
|
||||||
|
is_signed = false;
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
case 'o':
|
||||||
|
is_signed = false;
|
||||||
|
base = 8;
|
||||||
|
while (isspace(c)) {
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '+') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
c = stmGet(stmp);
|
||||||
|
} else if (c == '-') {
|
||||||
|
if (--width == 0) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
is_positive = false;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
stmUnget(stmp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
vall = 0UL;
|
||||||
|
|
||||||
|
/* If we don't have at least one additional eligible character, it's a matching failure */
|
||||||
|
if (sym_to_val(c, base) == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (width--) {
|
||||||
|
digit = sym_to_val(c, base);
|
||||||
|
if (digit == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vall = (vall * base) + digit;
|
||||||
|
c = stmGet(stmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_positive) {
|
||||||
|
vall = -1 * vall;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf) {
|
||||||
|
if (is_long && is_signed) {
|
||||||
|
*((signed long*)buf) = vall;
|
||||||
|
} else if (is_long && !is_signed) {
|
||||||
|
*((unsigned long*)buf) = vall;
|
||||||
|
} else if (!is_long && is_signed) {
|
||||||
|
*((signed int*)buf) = vall;
|
||||||
|
} else if (!is_long && !is_signed) {
|
||||||
|
*((unsigned int*)buf) = vall;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f = *fmt++;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
stmUnget(stmp, c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief System formatted input function.
|
||||||
|
* @details This function implements a minimal @p scanf() like functionality
|
||||||
|
* with input from a @p BufferedStream.
|
||||||
|
* The general parameters format is: %[*][width][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] chp pointer to a @p BufferedStream implementing object
|
||||||
|
* @param[in] fmt formatting string
|
||||||
|
* @return The number parameters in ap that have been successfully
|
||||||
|
* filled. This does not conform to the standard in that if
|
||||||
|
* a failure (either matching or input) occurs before any
|
||||||
|
* parameters are assigned, the function will return 0.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
int chscanf(sequential_stream_i *stmp, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
retval = chvscanf(stmp, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief System formatted input function.
|
||||||
|
* @details This function implements a minimal @p snscanf()-like functionality.
|
||||||
|
* The general parameters format is: %[*][width][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] str pointer to a buffer
|
||||||
|
* @param[in] size size of the buffer
|
||||||
|
* @param[in] fmt formatting string
|
||||||
|
* @return The number parameters in ap that have been successfully
|
||||||
|
* filled. This does not conform to the standard in that if
|
||||||
|
* a failure (either matching or input) occurs before any
|
||||||
|
* parameters are assigned, the function will return 0.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
int chsnscanf(char *str, size_t size, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/* Performing the scan operation.*/
|
||||||
|
va_start(ap, fmt);
|
||||||
|
retval = chvsnscanf(str, size, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
/* Return number of receiving arguments successfully assigned.*/
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief System formatted input function.
|
||||||
|
* @details This function implements a minimal @p vsnscanf()-like functionality.
|
||||||
|
* The general parameters format is: %[*][width][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] str pointer to a buffer
|
||||||
|
* @param[in] size size of the buffer
|
||||||
|
* @param[in] fmt formatting string
|
||||||
|
* @param[in] ap list of parameters
|
||||||
|
* @return The number parameters in ap that have been successfully
|
||||||
|
* filled. This does not conform to the standard in that if
|
||||||
|
* a failure (either matching or input) occurs before any
|
||||||
|
* parameters are assigned, the function will return 0.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
int chvsnscanf(char *str, size_t size, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
memory_stream_c ms;
|
||||||
|
size_t size_wo_nul;
|
||||||
|
|
||||||
|
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 scan operation using the common code and
|
||||||
|
return number of receiving arguments successfully assigned.*/
|
||||||
|
return chvscanf(oopGetIf(&ms, stm), fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
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 nullstreams.c
|
||||||
|
* @brief Generated Null Streams source.
|
||||||
|
* @note This is a generated file, do not edit directly.
|
||||||
|
*
|
||||||
|
* @addtogroup NULLSTREAMS
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nullstreams.h"
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module local definitions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module local macros. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module exported variables. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module local types. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module local variables. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module local functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module exported functions. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/*===========================================================================*/
|
||||||
|
/* Module class "null_stream_c" methods. */
|
||||||
|
/*===========================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Interfaces implementation of null_stream_c
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @memberof null_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 __nullstm_stm_write_impl(void *ip, const uint8_t *bp, size_t n) {
|
||||||
|
null_stream_c *self = oopIfGetOwner(null_stream_c, ip);
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)bp;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof null_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 __nullstm_stm_read_impl(void *ip, uint8_t *bp, size_t n) {
|
||||||
|
null_stream_c *self = oopIfGetOwner(null_stream_c, ip);
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)bp;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof null_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 __nullstm_stm_put_impl(void *ip, uint8_t b) {
|
||||||
|
null_stream_c *self = oopIfGetOwner(null_stream_c, ip);
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)b;
|
||||||
|
|
||||||
|
return STM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof null_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 __nullstm_stm_get_impl(void *ip) {
|
||||||
|
null_stream_c *self = oopIfGetOwner(null_stream_c, ip);
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof null_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 __nullstm_stm_unget_impl(void *ip, int b) {
|
||||||
|
null_stream_c *self = oopIfGetOwner(null_stream_c, ip);
|
||||||
|
|
||||||
|
(void)self;
|
||||||
|
(void)b;
|
||||||
|
|
||||||
|
return STM_RESET;
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Methods implementations of null_stream_c
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @memberof null_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 null_stream_c instance to be
|
||||||
|
* initialized.
|
||||||
|
* @param[in] vmt VMT pointer for the new object.
|
||||||
|
* @return A new reference to the object.
|
||||||
|
*/
|
||||||
|
void *__nullstm_objinit_impl(void *ip, const void *vmt) {
|
||||||
|
null_stream_c *self = (null_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 nullstm_stm_vmt = {
|
||||||
|
.instance_offset = offsetof(null_stream_c, stm),
|
||||||
|
.write = __nullstm_stm_write_impl,
|
||||||
|
.read = __nullstm_stm_read_impl,
|
||||||
|
.put = __nullstm_stm_put_impl,
|
||||||
|
.get = __nullstm_stm_get_impl,
|
||||||
|
.unget = __nullstm_stm_unget_impl
|
||||||
|
};
|
||||||
|
oopIfObjectInit(&self->stm, &nullstm_stm_vmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No initialization code.*/
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @memberof null_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 null_stream_c instance to be
|
||||||
|
* disposed.
|
||||||
|
*/
|
||||||
|
void __nullstm_dispose_impl(void *ip) {
|
||||||
|
null_stream_c *self = (null_stream_c *)ip;
|
||||||
|
|
||||||
|
/* No finalization code.*/
|
||||||
|
(void)self;
|
||||||
|
|
||||||
|
/* Finalization of the ancestors-defined parts.*/
|
||||||
|
__bo_dispose_impl(self);
|
||||||
|
}
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief VMT structure of null stream class.
|
||||||
|
* @note It is public because accessed by the inlined constructor.
|
||||||
|
*/
|
||||||
|
const struct null_stream_vmt __null_stream_vmt = {
|
||||||
|
.dispose = __nullstm_dispose_impl
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @} */
|
Loading…
Reference in New Issue