lib_libvscanf.c:Add buffer data type conversion interface.

Signed-off-by: likun17 <likun17@xiaomi.com>
This commit is contained in:
likun17 2024-01-02 10:19:33 +08:00 committed by Xiang Xiao
parent 89a3f28a76
commit 71876ae098
3 changed files with 169 additions and 27 deletions

View File

@ -746,6 +746,19 @@ int lib_vsprintf(FAR struct lib_outstream_s *stream,
int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *src, va_list ap) scanf_like(3, 0);
/****************************************************************************
* Name: lib_bscanf
*
* Description:
* Convert data into a structure according to standard formatting protocols.
* For string arrays, please use "%{length}s" or "%{length}c" to specify
* the length.
*
****************************************************************************/
int lib_bscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *fmt, FAR void *data);
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -1,11 +1,11 @@
# lib_libbsprintf
This function is mainly used to output the contents of the input structure. Most standards follow the standards of printf and scanf.
# lib_bsprintf
This function is mainly used to output the contents of the input structure. Supports standard formats for printf and scanf.
For detailed parameters, see:
1. https://en.cppreference.com/w/c/io/fprintf
2. https://en.cppreference.com/w/c/io/fscanf
- **special**:
1. Float use %hf, and double for all others.
1. Float use %hf, "%f" or "%lf" is double, "%Lf" is long double.
2. The char array is specified with %.xs. for example: "char t[30]" is specified with "%.30s", char a [20] - " %.20s "
3. "%u" is unsigned int.
4. "%d" is int.
@ -93,3 +93,63 @@
lib_stream_flush(&outstream.common);
#endif
~~~
# lib_bscanf
This function adds a formatted standard scanf string to the structure(lib_bscanf).
1. https://zh.cppreference.com/w/c/io/fscanf
- **special**:
1. Please use %lf for double precision, "%hf" or "%f" for float, long double ("%Lf") is not supported.
2. Please use %hhd or %hhu for a single char or unsigned char.
3. Use %hd or %hu for short int or unsigned short int.
4. When using %s or %c, please specify the length of the char array, such as %32s, %32c.
5. %s will check the string for spaces. When there are spaces in the string, it will be truncated. If you want to use string with spaces, please use %{length}c, but make sure that the length of the string can fill the array, otherwise an error will occur.
6. %[] collection and %n are not supported.
- **demo**
1. **struct**:
Same as above
1. **format string**:
~~~
#define TOSTR(str) #str
#define TONNAME(name) TOSTR(name)
#define v_uint8_t 97
#define v_uint16_t 19299
#define v_uint32_t 22155
......
#define v_l_double -9299.9299929912122464755474
char bflag[] = "%hhu%hu%u%hhd%hd%d%f%lf%32s%llu%lld%hhd%hhu%hd%hu%d%u%ld%lu%lld%llu%zu%ld";
char binput[] = TONNAME(v_uint8_t) \
" " TONNAME(v_uint16_t) \
" " TONNAME(v_uint32_t) \
" " TONNAME(v_int8_t) \
" " TONNAME(v_int16_t) \
" " TONNAME(v_int32_t) \
" " TONNAME(v_float) \
" " TONNAME(v_double) \
" " TONNAME(v_char_arr) \
" " TONNAME(v_uint64_t) \
" " TONNAME(v_int64_t) \
" " TONNAME(v_char) \
" " TONNAME(v_u_char) \
" " TONNAME(v_s_int) \
" " TONNAME(v_u_s_int) \
" " TONNAME(v_int) \
" " TONNAME(v_u_int) \
" " TONNAME(v_long) \
" " TONNAME(v_u_long) \
" " TONNAME(v_l_l) \
" " TONNAME(v_u_l_l) \
" " TONNAME(v_size_t) \
" " TONNAME(v_l_double);
~~~
3. **use**:
~~~
struct test vg;
ret = lib_bscanf(binput, bflag, &vg);
~~~

View File

@ -66,6 +66,29 @@
# define fmt_char(fmt) (*(fmt))
#endif
#define buf_arg(buf, type) \
((buf) = (FAR char *)(buf) + sizeof(*(type)0), \
(type)((FAR char *)(buf) - sizeof(*(type)0)))
#define next_arg(varg, vabuf, type) \
(varg) ? va_arg((vabuf).ap, type) : buf_arg((vabuf).buf, type)
#define buf_arg_width(buf, type, width) \
((buf) = (FAR char *)(buf) + (width), (type)((FAR char *)(buf) - (width)))
#define next_arg_width(varg, vabuf, type, width) \
(varg) ? va_arg((vabuf).ap, type) : buf_arg_width((vabuf).buf, type, width)
/****************************************************************************
* Private Types
****************************************************************************/
union vabuf_u
{
FAR const void *buf;
va_list ap;
};
/****************************************************************************
* Private Functions
****************************************************************************/
@ -190,20 +213,17 @@ doexit:
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lib_vscanf
* Name: vscanf_internal
*
* Description:
* Stream-oriented implementation that underlies scanf family: scanf,
* fscanf, vfscanf, sscanf, and vsscanf
* fscanf, vfscanf, sscanf, vsscanf and bscanf.
*
****************************************************************************/
int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *fmt, va_list ap)
static int vscanf_internal(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *fmt, bool varg,
union vabuf_u vabuf)
{
int c;
FAR char *tv;
@ -392,7 +412,7 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
tv = NULL; /* To avoid warnings about begin uninitialized */
if (!noassign)
{
tv = va_arg(ap, FAR char *);
tv = next_arg_width(varg, vabuf, FAR char *, width);
tv[0] = '\0';
}
@ -454,7 +474,7 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
tv = NULL; /* To avoid warnings about begin uninitialized */
if (!noassign)
{
tv = va_arg(ap, FAR char *);
tv = next_arg_width(varg, vabuf, FAR char *, width);
tv[0] = '\0';
}
@ -513,7 +533,7 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
tv = NULL; /* To avoid warnings about being uninitialized */
if (!noassign)
{
tv = va_arg(ap, FAR char *);
tv = next_arg_width(varg, vabuf, FAR char *, width);
tv[0] = '\0';
}
@ -583,29 +603,30 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
switch (modifier)
{
case HH_MOD:
pchar = va_arg(ap, FAR unsigned char *);
pchar = next_arg(varg, vabuf, FAR unsigned char *);
*pchar = 0;
break;
case H_MOD:
pshort = va_arg(ap, FAR unsigned short *);
pshort = next_arg(varg, vabuf, FAR unsigned short *);
*pshort = 0;
break;
case NO_MOD:
pint = va_arg(ap, FAR unsigned int *);
pint = next_arg(varg, vabuf, FAR unsigned int *);
*pint = 0;
break;
default:
case L_MOD:
plong = va_arg(ap, FAR unsigned long *);
plong = next_arg(varg, vabuf, FAR unsigned long *);
*plong = 0;
break;
#ifdef CONFIG_HAVE_LONG_LONG
case LL_MOD:
plonglong = va_arg(ap, FAR unsigned long long *);
plonglong = next_arg(varg, vabuf,
FAR unsigned long long *);
*plonglong = 0;
break;
#endif
@ -975,14 +996,14 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
#ifdef CONFIG_HAVE_DOUBLE
if (modifier >= L_MOD)
{
pd = va_arg(ap, FAR double *);
pd = next_arg(varg, vabuf, FAR double *);
*pd = 0.0;
}
else
#endif
#ifdef CONFIG_HAVE_FLOAT
{
pf = va_arg(ap, FAR float *);
pf = next_arg(varg, vabuf, FAR float *);
*pf = 0.0;
}
#endif
@ -1178,29 +1199,30 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
switch (modifier)
{
case HH_MOD:
pchar = va_arg(ap, FAR unsigned char *);
pchar = next_arg(varg, vabuf, FAR unsigned char *);
*pchar = (unsigned char)nchars;
break;
case H_MOD:
pshort = va_arg(ap, FAR unsigned short *);
pshort = next_arg(varg, vabuf, FAR unsigned short *);
*pshort = (unsigned short)nchars;
break;
case NO_MOD:
pint = va_arg(ap, FAR unsigned int *);
pint = next_arg(varg, vabuf, FAR unsigned int *);
*pint = (unsigned int)nchars;
break;
default:
case L_MOD:
plong = va_arg(ap, FAR unsigned long *);
plong = next_arg(varg, vabuf, FAR unsigned long *);
*plong = (unsigned long)nchars;
break;
#ifdef CONFIG_HAVE_LONG_LONG
case LL_MOD:
plonglong = va_arg(ap, FAR unsigned long long *);
plonglong = next_arg(varg, vabuf,
FAR unsigned long long *);
*plonglong = (unsigned long long)nchars;
break;
#endif
@ -1268,3 +1290,50 @@ int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
*lastc = c;
return (count || !conv) ? assigncount : EOF;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: lib_vscanf
*
* Description:
* Stream-oriented implementation that underlies scanf family: scanf,
* fscanf, vfscanf, sscanf, and vsscanf
*
****************************************************************************/
int lib_vscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *fmt, va_list ap)
{
union vabuf_u vabuf;
int ret;
va_copy(vabuf.ap, ap);
ret = vscanf_internal(stream, lastc, fmt, true, vabuf);
va_end(vabuf.ap);
return ret;
}
/****************************************************************************
* Name: lib_bscanf
*
* Description:
* Convert data into a structure according to standard formatting protocols.
* For string arrays, please use "%{length}s" or "%{length}c" to specify
* the length.
*
****************************************************************************/
int lib_bscanf(FAR struct lib_instream_s *stream, FAR int *lastc,
FAR const IPTR char *fmt, FAR void *data)
{
union vabuf_u vabuf =
{
data
};
return vscanf_internal(stream, lastc, fmt, false, vabuf);
}