mirror of
https://gitlab.os-k.eu/os-k-team/os-k.git
synced 2023-08-25 14:03:10 +02:00
229 lines
5.4 KiB
C
229 lines
5.4 KiB
C
//----------------------------------------------------------------------------//
|
|
// GNU GPL OS/K //
|
|
// //
|
|
// Desc: Buffer library //
|
|
// //
|
|
// //
|
|
// Copyright © 2018-2019 The OS/K Team //
|
|
// //
|
|
// This file is part of OS/K. //
|
|
// //
|
|
// OS/K 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, either version 3 of the License, or //
|
|
// any later version. //
|
|
// //
|
|
// OS/K 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 OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
|
//----------------------------------------------------------------------------//
|
|
|
|
#include <lib/buf.h>
|
|
|
|
//
|
|
// Builds string reading from buf according to fmt
|
|
//
|
|
size_t BScanFromBuf(Buffer_t *buf, const char *fmt, ...)
|
|
{
|
|
size_t sz;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
ExAcquireLock(&buf->lock);
|
|
sz = vbscanf(buf, fmt, ap);
|
|
ExReleaseLock(&buf->lock);
|
|
va_end(ap);
|
|
|
|
return sz;
|
|
}
|
|
|
|
size_t BScanFromBufV(Buffer_t *buf, const char *fmt, va_list ap)
|
|
{
|
|
size_t sz;
|
|
|
|
ExAcquireLock(&buf->lock);
|
|
sz = vbscanf(buf, fmt, ap);
|
|
ExReleaseLock(&buf->lock);
|
|
|
|
return sz;
|
|
}
|
|
|
|
size_t bscanf(Buffer_t *buf, const char *fmt, ...)
|
|
{
|
|
size_t sz;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
sz = vbscanf(buf, fmt, ap);
|
|
va_end(ap);
|
|
|
|
return sz;
|
|
}
|
|
|
|
size_t vbscanf(Buffer_t *buf, const char *fmt, va_list ap)
|
|
{
|
|
error_t rc = EOK;
|
|
|
|
size_t readcnt = 0;
|
|
uchar ch = 0;
|
|
char *chptr;
|
|
|
|
bool l, h;
|
|
|
|
size_t width;
|
|
bool ignore; // '*' modifier, don't write to va_list for current mod
|
|
|
|
if (!buf || !fmt) { seterrno(EINVAL); return 0; }
|
|
if (buf->flags & (BF_EOF|BF_ERR)) { seterrno(EENDF); return 0; }
|
|
if (buf->state != BS_RDWR && buf->state != BS_WRONLY) {
|
|
seterrno(EBADF);
|
|
return 0;
|
|
}
|
|
|
|
// Progress in format string
|
|
while (*fmt && !rc) {
|
|
|
|
// Skip all kinds of whitespaces
|
|
if (isspace(*fmt)) {
|
|
|
|
another_space:
|
|
rc = bgetc(buf, &ch);
|
|
|
|
if (!rc) break;
|
|
|
|
// Put back non-whitespaces and progress
|
|
if (!isspace(ch)) {
|
|
buf->rp--;
|
|
do { fmt++; } while (isspace(*fmt));
|
|
continue;
|
|
}
|
|
|
|
else goto another_space;
|
|
}
|
|
|
|
// Deal with all non-'%' non-whitespace characters
|
|
if (*fmt != '%') {
|
|
rc = bgetc(buf, &ch);
|
|
|
|
// Is it what we expected?
|
|
if (!rc && ch != *fmt) {
|
|
// No, so put it back
|
|
buf->rp--;
|
|
break;
|
|
}
|
|
|
|
// We don't do anything with these characters
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// %[*][width][modifier]type
|
|
//
|
|
|
|
// Skip the %
|
|
fmt++;
|
|
|
|
// '%%' type
|
|
if (*fmt == '%') {
|
|
rc = bgetc(buf, &ch);
|
|
|
|
if (!rc && ch != '%') {
|
|
buf->rp--;
|
|
break;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
l = h = 0;
|
|
width = 0;
|
|
ignore = 0;
|
|
|
|
// Don't write to variable
|
|
if (*fmt == '*') {
|
|
ignore = 1;
|
|
fmt++;
|
|
}
|
|
|
|
// Extract width field
|
|
while (isdigit(*fmt)) {
|
|
width = 10 * width + (*fmt - '0');
|
|
fmt++;
|
|
}
|
|
|
|
//
|
|
// Extract length field
|
|
//
|
|
|
|
if (*fmt == 'l') {
|
|
l = 1;
|
|
fmt++;
|
|
}
|
|
|
|
else if (*fmt == 'h') {
|
|
h = 1;
|
|
fmt++;
|
|
}
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// Read character(s)
|
|
if (*fmt == 'c') {
|
|
if (width == 0) width = 1;
|
|
|
|
// For >1 width, read that many characters
|
|
// then store them in successive argument pointers
|
|
for (; width; width--) {
|
|
rc = bgetc(buf, &ch);
|
|
if (!rc) break;
|
|
if (ignore) continue;
|
|
|
|
chptr = va_arg(ap, char *);
|
|
*chptr = (char)ch;
|
|
readcnt++;
|
|
}
|
|
}
|
|
|
|
// Decimal integer
|
|
else if (*fmt == 'd') {
|
|
;
|
|
}
|
|
}
|
|
|
|
// For debugging purposes
|
|
assert(!rc && "vbscanf() error");
|
|
seterrno(rc);
|
|
|
|
return readcnt;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|