lib_libvscanf.c:Add buffer data type conversion interface.
Signed-off-by: likun17 <likun17@xiaomi.com>
This commit is contained in:
parent
89a3f28a76
commit
71876ae098
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -92,4 +92,64 @@
|
|||
|
||||
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);
|
||||
~~~
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue