1d5ac70f0Sopenharmony_ci/** 2d5ac70f0Sopenharmony_ci * \file input.c 3d5ac70f0Sopenharmony_ci * \brief Generic stdio-like input interface 4d5ac70f0Sopenharmony_ci * \author Abramo Bagnara <abramo@alsa-project.org> 5d5ac70f0Sopenharmony_ci * \date 2000 6d5ac70f0Sopenharmony_ci * 7d5ac70f0Sopenharmony_ci * Generic stdio-like input interface 8d5ac70f0Sopenharmony_ci */ 9d5ac70f0Sopenharmony_ci/* 10d5ac70f0Sopenharmony_ci * Input object 11d5ac70f0Sopenharmony_ci * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org> 12d5ac70f0Sopenharmony_ci * 13d5ac70f0Sopenharmony_ci * 14d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 15d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 16d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 17d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 18d5ac70f0Sopenharmony_ci * 19d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 20d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 21d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 23d5ac70f0Sopenharmony_ci * 24d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 25d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 26d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 27d5ac70f0Sopenharmony_ci * 28d5ac70f0Sopenharmony_ci */ 29d5ac70f0Sopenharmony_ci 30d5ac70f0Sopenharmony_ci#include "local.h" 31d5ac70f0Sopenharmony_ci#include <stdarg.h> 32d5ac70f0Sopenharmony_ci#include <stdio.h> 33d5ac70f0Sopenharmony_ci#include <stdlib.h> 34d5ac70f0Sopenharmony_ci#include <unistd.h> 35d5ac70f0Sopenharmony_ci 36d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 37d5ac70f0Sopenharmony_ci 38d5ac70f0Sopenharmony_citypedef struct _snd_input_ops { 39d5ac70f0Sopenharmony_ci int (*close)(snd_input_t *input); 40d5ac70f0Sopenharmony_ci int (*scan)(snd_input_t *input, const char *format, va_list args); 41d5ac70f0Sopenharmony_ci char *(*(gets))(snd_input_t *input, char *str, size_t size); 42d5ac70f0Sopenharmony_ci int (*getch)(snd_input_t *input); 43d5ac70f0Sopenharmony_ci int (*ungetch)(snd_input_t *input, int c); 44d5ac70f0Sopenharmony_ci} snd_input_ops_t; 45d5ac70f0Sopenharmony_ci 46d5ac70f0Sopenharmony_cistruct _snd_input { 47d5ac70f0Sopenharmony_ci snd_input_type_t type; 48d5ac70f0Sopenharmony_ci const snd_input_ops_t *ops; 49d5ac70f0Sopenharmony_ci void *private_data; 50d5ac70f0Sopenharmony_ci}; 51d5ac70f0Sopenharmony_ci#endif 52d5ac70f0Sopenharmony_ci 53d5ac70f0Sopenharmony_ci/** 54d5ac70f0Sopenharmony_ci * \brief Closes an input handle. 55d5ac70f0Sopenharmony_ci * \param input The input handle to be closed. 56d5ac70f0Sopenharmony_ci * \return Zero if successful, otherwise a negative error code. 57d5ac70f0Sopenharmony_ci */ 58d5ac70f0Sopenharmony_ciint snd_input_close(snd_input_t *input) 59d5ac70f0Sopenharmony_ci{ 60d5ac70f0Sopenharmony_ci int err = input->ops->close(input); 61d5ac70f0Sopenharmony_ci free(input); 62d5ac70f0Sopenharmony_ci return err; 63d5ac70f0Sopenharmony_ci} 64d5ac70f0Sopenharmony_ci 65d5ac70f0Sopenharmony_ci/** 66d5ac70f0Sopenharmony_ci * \brief Reads formatted input (like \c fscanf(3)) from an input handle. 67d5ac70f0Sopenharmony_ci * \param input The input handle. 68d5ac70f0Sopenharmony_ci * \param format Format string in \c fscanf format. 69d5ac70f0Sopenharmony_ci * \param ... Other \c fscanf arguments. 70d5ac70f0Sopenharmony_ci * \return The number of input items assigned, or \c EOF. 71d5ac70f0Sopenharmony_ci * 72d5ac70f0Sopenharmony_ci * \bug Reading from a memory buffer doesn't work. 73d5ac70f0Sopenharmony_ci */ 74d5ac70f0Sopenharmony_ciint snd_input_scanf(snd_input_t *input, const char *format, ...) 75d5ac70f0Sopenharmony_ci{ 76d5ac70f0Sopenharmony_ci int result; 77d5ac70f0Sopenharmony_ci va_list args; 78d5ac70f0Sopenharmony_ci va_start(args, format); 79d5ac70f0Sopenharmony_ci result = input->ops->scan(input, format, args); 80d5ac70f0Sopenharmony_ci va_end(args); 81d5ac70f0Sopenharmony_ci return result; 82d5ac70f0Sopenharmony_ci} 83d5ac70f0Sopenharmony_ci 84d5ac70f0Sopenharmony_ci/** 85d5ac70f0Sopenharmony_ci * \brief Reads a line from an input handle (like \c fgets(3)). 86d5ac70f0Sopenharmony_ci * \param input The input handle. 87d5ac70f0Sopenharmony_ci * \param str Address of the destination buffer. 88d5ac70f0Sopenharmony_ci * \param size The size of the destination buffer. 89d5ac70f0Sopenharmony_ci * \return Pointer to the buffer if successful, otherwise \c NULL. 90d5ac70f0Sopenharmony_ci * 91d5ac70f0Sopenharmony_ci * Like \c fgets, the returned string is zero-terminated, and contains 92d5ac70f0Sopenharmony_ci * the new-line character \c '\\n' if the line fits into the buffer. 93d5ac70f0Sopenharmony_ci */ 94d5ac70f0Sopenharmony_cichar *snd_input_gets(snd_input_t *input, char *str, size_t size) 95d5ac70f0Sopenharmony_ci{ 96d5ac70f0Sopenharmony_ci return (input->ops->gets)(input, str, size); 97d5ac70f0Sopenharmony_ci} 98d5ac70f0Sopenharmony_ci 99d5ac70f0Sopenharmony_ci/** 100d5ac70f0Sopenharmony_ci * \brief Reads a character from an input handle (like \c fgetc(3)). 101d5ac70f0Sopenharmony_ci * \param input The input handle. 102d5ac70f0Sopenharmony_ci * \return The character read, or \c EOF on end of file or error. 103d5ac70f0Sopenharmony_ci */ 104d5ac70f0Sopenharmony_ciint snd_input_getc(snd_input_t *input) 105d5ac70f0Sopenharmony_ci{ 106d5ac70f0Sopenharmony_ci return input->ops->getch(input); 107d5ac70f0Sopenharmony_ci} 108d5ac70f0Sopenharmony_ci 109d5ac70f0Sopenharmony_ci/** 110d5ac70f0Sopenharmony_ci * \brief Puts the last character read back to an input handle (like \c ungetc(3)). 111d5ac70f0Sopenharmony_ci * \param input The input handle. 112d5ac70f0Sopenharmony_ci * \param c The character to push back. 113d5ac70f0Sopenharmony_ci * \return The character pushed back, or \c EOF on error. 114d5ac70f0Sopenharmony_ci */ 115d5ac70f0Sopenharmony_ciint snd_input_ungetc(snd_input_t *input, int c) 116d5ac70f0Sopenharmony_ci{ 117d5ac70f0Sopenharmony_ci return input->ops->ungetch(input, c); 118d5ac70f0Sopenharmony_ci} 119d5ac70f0Sopenharmony_ci 120d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 121d5ac70f0Sopenharmony_citypedef struct _snd_input_stdio { 122d5ac70f0Sopenharmony_ci int close; 123d5ac70f0Sopenharmony_ci FILE *fp; 124d5ac70f0Sopenharmony_ci} snd_input_stdio_t; 125d5ac70f0Sopenharmony_ci 126d5ac70f0Sopenharmony_cistatic int snd_input_stdio_close(snd_input_t *input ATTRIBUTE_UNUSED) 127d5ac70f0Sopenharmony_ci{ 128d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio = input->private_data; 129d5ac70f0Sopenharmony_ci if (stdio->close) 130d5ac70f0Sopenharmony_ci fclose(stdio->fp); 131d5ac70f0Sopenharmony_ci free(stdio); 132d5ac70f0Sopenharmony_ci return 0; 133d5ac70f0Sopenharmony_ci} 134d5ac70f0Sopenharmony_ci 135d5ac70f0Sopenharmony_cistatic int snd_input_stdio_scan(snd_input_t *input, const char *format, va_list args) 136d5ac70f0Sopenharmony_ci{ 137d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio = input->private_data; 138d5ac70f0Sopenharmony_ci extern int vfscanf(FILE *, const char *, va_list); 139d5ac70f0Sopenharmony_ci return vfscanf(stdio->fp, format, args); 140d5ac70f0Sopenharmony_ci} 141d5ac70f0Sopenharmony_ci 142d5ac70f0Sopenharmony_cistatic char *snd_input_stdio_gets(snd_input_t *input, char *str, size_t size) 143d5ac70f0Sopenharmony_ci{ 144d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio = input->private_data; 145d5ac70f0Sopenharmony_ci return fgets(str, (int) size, stdio->fp); 146d5ac70f0Sopenharmony_ci} 147d5ac70f0Sopenharmony_ci 148d5ac70f0Sopenharmony_cistatic int snd_input_stdio_getc(snd_input_t *input) 149d5ac70f0Sopenharmony_ci{ 150d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio = input->private_data; 151d5ac70f0Sopenharmony_ci return getc(stdio->fp); 152d5ac70f0Sopenharmony_ci} 153d5ac70f0Sopenharmony_ci 154d5ac70f0Sopenharmony_cistatic int snd_input_stdio_ungetc(snd_input_t *input, int c) 155d5ac70f0Sopenharmony_ci{ 156d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio = input->private_data; 157d5ac70f0Sopenharmony_ci return ungetc(c, stdio->fp); 158d5ac70f0Sopenharmony_ci} 159d5ac70f0Sopenharmony_ci 160d5ac70f0Sopenharmony_cistatic const snd_input_ops_t snd_input_stdio_ops = { 161d5ac70f0Sopenharmony_ci .close = snd_input_stdio_close, 162d5ac70f0Sopenharmony_ci .scan = snd_input_stdio_scan, 163d5ac70f0Sopenharmony_ci .gets = snd_input_stdio_gets, 164d5ac70f0Sopenharmony_ci .getch = snd_input_stdio_getc, 165d5ac70f0Sopenharmony_ci .ungetch = snd_input_stdio_ungetc, 166d5ac70f0Sopenharmony_ci}; 167d5ac70f0Sopenharmony_ci#endif 168d5ac70f0Sopenharmony_ci 169d5ac70f0Sopenharmony_ci/** 170d5ac70f0Sopenharmony_ci * \brief Creates a new input object using an existing stdio \c FILE pointer. 171d5ac70f0Sopenharmony_ci * \param inputp The function puts the pointer to the new input object 172d5ac70f0Sopenharmony_ci * at the address specified by \p inputp. 173d5ac70f0Sopenharmony_ci * \param fp The \c FILE pointer to read from. 174d5ac70f0Sopenharmony_ci * Reading begins at the current file position. 175d5ac70f0Sopenharmony_ci * \param _close Close flag. Set this to 1 if #snd_input_close should close 176d5ac70f0Sopenharmony_ci * \p fp by calling \c fclose. 177d5ac70f0Sopenharmony_ci * \return Zero if successful, otherwise a negative error code. 178d5ac70f0Sopenharmony_ci */ 179d5ac70f0Sopenharmony_ciint snd_input_stdio_attach(snd_input_t **inputp, FILE *fp, int _close) 180d5ac70f0Sopenharmony_ci{ 181d5ac70f0Sopenharmony_ci snd_input_t *input; 182d5ac70f0Sopenharmony_ci snd_input_stdio_t *stdio; 183d5ac70f0Sopenharmony_ci assert(inputp && fp); 184d5ac70f0Sopenharmony_ci stdio = calloc(1, sizeof(*stdio)); 185d5ac70f0Sopenharmony_ci if (!stdio) 186d5ac70f0Sopenharmony_ci return -ENOMEM; 187d5ac70f0Sopenharmony_ci input = calloc(1, sizeof(*input)); 188d5ac70f0Sopenharmony_ci if (!input) { 189d5ac70f0Sopenharmony_ci free(stdio); 190d5ac70f0Sopenharmony_ci return -ENOMEM; 191d5ac70f0Sopenharmony_ci } 192d5ac70f0Sopenharmony_ci stdio->fp = fp; 193d5ac70f0Sopenharmony_ci stdio->close = _close; 194d5ac70f0Sopenharmony_ci input->type = SND_INPUT_STDIO; 195d5ac70f0Sopenharmony_ci input->ops = &snd_input_stdio_ops; 196d5ac70f0Sopenharmony_ci input->private_data = stdio; 197d5ac70f0Sopenharmony_ci *inputp = input; 198d5ac70f0Sopenharmony_ci return 0; 199d5ac70f0Sopenharmony_ci} 200d5ac70f0Sopenharmony_ci 201d5ac70f0Sopenharmony_ci/** 202d5ac70f0Sopenharmony_ci * \brief Creates a new input object reading from a file. 203d5ac70f0Sopenharmony_ci * \param inputp The functions puts the pointer to the new input object 204d5ac70f0Sopenharmony_ci * at the address specified by \p inputp. 205d5ac70f0Sopenharmony_ci * \param file The name of the file to read from. 206d5ac70f0Sopenharmony_ci * \param mode The open mode, like \c fopen(3). 207d5ac70f0Sopenharmony_ci * \return Zero if successful, otherwise a negative error code. 208d5ac70f0Sopenharmony_ci */ 209d5ac70f0Sopenharmony_ciint snd_input_stdio_open(snd_input_t **inputp, const char *file, const char *mode) 210d5ac70f0Sopenharmony_ci{ 211d5ac70f0Sopenharmony_ci int err; 212d5ac70f0Sopenharmony_ci FILE *fp = fopen(file, mode); 213d5ac70f0Sopenharmony_ci if (!fp) { 214d5ac70f0Sopenharmony_ci //SYSERR("fopen"); 215d5ac70f0Sopenharmony_ci return -errno; 216d5ac70f0Sopenharmony_ci } 217d5ac70f0Sopenharmony_ci err = snd_input_stdio_attach(inputp, fp, 1); 218d5ac70f0Sopenharmony_ci if (err < 0) 219d5ac70f0Sopenharmony_ci fclose(fp); 220d5ac70f0Sopenharmony_ci return err; 221d5ac70f0Sopenharmony_ci} 222d5ac70f0Sopenharmony_ci 223d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 224d5ac70f0Sopenharmony_ci 225d5ac70f0Sopenharmony_citypedef struct _snd_input_buffer { 226d5ac70f0Sopenharmony_ci unsigned char *buf; 227d5ac70f0Sopenharmony_ci unsigned char *ptr; 228d5ac70f0Sopenharmony_ci size_t size; 229d5ac70f0Sopenharmony_ci} snd_input_buffer_t; 230d5ac70f0Sopenharmony_ci 231d5ac70f0Sopenharmony_cistatic int snd_input_buffer_close(snd_input_t *input) 232d5ac70f0Sopenharmony_ci{ 233d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer = input->private_data; 234d5ac70f0Sopenharmony_ci free(buffer->buf); 235d5ac70f0Sopenharmony_ci free(buffer); 236d5ac70f0Sopenharmony_ci return 0; 237d5ac70f0Sopenharmony_ci} 238d5ac70f0Sopenharmony_ci 239d5ac70f0Sopenharmony_cistatic int snd_input_buffer_scan(snd_input_t *input, const char *format, va_list args) 240d5ac70f0Sopenharmony_ci{ 241d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer = input->private_data; 242d5ac70f0Sopenharmony_ci extern int vsscanf(const char *, const char *, va_list); 243d5ac70f0Sopenharmony_ci /* FIXME: how can I obtain consumed chars count? */ 244d5ac70f0Sopenharmony_ci assert(0); 245d5ac70f0Sopenharmony_ci return vsscanf((char *)buffer->ptr, format, args); 246d5ac70f0Sopenharmony_ci} 247d5ac70f0Sopenharmony_ci 248d5ac70f0Sopenharmony_cistatic char *snd_input_buffer_gets(snd_input_t *input, char *str, size_t size) 249d5ac70f0Sopenharmony_ci{ 250d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer = input->private_data; 251d5ac70f0Sopenharmony_ci size_t bsize = buffer->size; 252d5ac70f0Sopenharmony_ci while (--size > 0 && bsize > 0) { 253d5ac70f0Sopenharmony_ci unsigned char c = *buffer->ptr++; 254d5ac70f0Sopenharmony_ci bsize--; 255d5ac70f0Sopenharmony_ci *str++ = c; 256d5ac70f0Sopenharmony_ci if (c == '\n') 257d5ac70f0Sopenharmony_ci break; 258d5ac70f0Sopenharmony_ci } 259d5ac70f0Sopenharmony_ci if (bsize == buffer->size) 260d5ac70f0Sopenharmony_ci return NULL; 261d5ac70f0Sopenharmony_ci buffer->size = bsize; 262d5ac70f0Sopenharmony_ci *str = '\0'; 263d5ac70f0Sopenharmony_ci return str; 264d5ac70f0Sopenharmony_ci} 265d5ac70f0Sopenharmony_ci 266d5ac70f0Sopenharmony_cistatic int snd_input_buffer_getc(snd_input_t *input) 267d5ac70f0Sopenharmony_ci{ 268d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer = input->private_data; 269d5ac70f0Sopenharmony_ci if (buffer->size == 0) 270d5ac70f0Sopenharmony_ci return EOF; 271d5ac70f0Sopenharmony_ci buffer->size--; 272d5ac70f0Sopenharmony_ci return *buffer->ptr++; 273d5ac70f0Sopenharmony_ci} 274d5ac70f0Sopenharmony_ci 275d5ac70f0Sopenharmony_cistatic int snd_input_buffer_ungetc(snd_input_t *input, int c) 276d5ac70f0Sopenharmony_ci{ 277d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer = input->private_data; 278d5ac70f0Sopenharmony_ci if (buffer->ptr == buffer->buf) 279d5ac70f0Sopenharmony_ci return EOF; 280d5ac70f0Sopenharmony_ci buffer->ptr--; 281d5ac70f0Sopenharmony_ci assert(*buffer->ptr == (unsigned char) c); 282d5ac70f0Sopenharmony_ci buffer->size++; 283d5ac70f0Sopenharmony_ci return c; 284d5ac70f0Sopenharmony_ci} 285d5ac70f0Sopenharmony_ci 286d5ac70f0Sopenharmony_cistatic const snd_input_ops_t snd_input_buffer_ops = { 287d5ac70f0Sopenharmony_ci .close = snd_input_buffer_close, 288d5ac70f0Sopenharmony_ci .scan = snd_input_buffer_scan, 289d5ac70f0Sopenharmony_ci .gets = snd_input_buffer_gets, 290d5ac70f0Sopenharmony_ci .getch = snd_input_buffer_getc, 291d5ac70f0Sopenharmony_ci .ungetch = snd_input_buffer_ungetc, 292d5ac70f0Sopenharmony_ci}; 293d5ac70f0Sopenharmony_ci#endif 294d5ac70f0Sopenharmony_ci 295d5ac70f0Sopenharmony_ci/** 296d5ac70f0Sopenharmony_ci * \brief Creates a new input object from a memory buffer. 297d5ac70f0Sopenharmony_ci * \param inputp The function puts the pointer to the new input object 298d5ac70f0Sopenharmony_ci * at the address specified by \p inputp. 299d5ac70f0Sopenharmony_ci * \param buf Address of the input buffer. 300d5ac70f0Sopenharmony_ci * \param size Size of the input buffer. 301d5ac70f0Sopenharmony_ci * \return Zero if successful, otherwise a negative error code. 302d5ac70f0Sopenharmony_ci * 303d5ac70f0Sopenharmony_ci * This functions creates a copy of the input buffer, so the application is 304d5ac70f0Sopenharmony_ci * not required to preserve the buffer after this function has been called. 305d5ac70f0Sopenharmony_ci */ 306d5ac70f0Sopenharmony_ciint snd_input_buffer_open(snd_input_t **inputp, const char *buf, ssize_t size) 307d5ac70f0Sopenharmony_ci{ 308d5ac70f0Sopenharmony_ci snd_input_t *input; 309d5ac70f0Sopenharmony_ci snd_input_buffer_t *buffer; 310d5ac70f0Sopenharmony_ci assert(inputp); 311d5ac70f0Sopenharmony_ci buffer = calloc(1, sizeof(*buffer)); 312d5ac70f0Sopenharmony_ci if (!buffer) 313d5ac70f0Sopenharmony_ci return -ENOMEM; 314d5ac70f0Sopenharmony_ci input = calloc(1, sizeof(*input)); 315d5ac70f0Sopenharmony_ci if (!input) { 316d5ac70f0Sopenharmony_ci free(buffer); 317d5ac70f0Sopenharmony_ci return -ENOMEM; 318d5ac70f0Sopenharmony_ci } 319d5ac70f0Sopenharmony_ci if (size < 0) 320d5ac70f0Sopenharmony_ci size = strlen(buf); 321d5ac70f0Sopenharmony_ci buffer->buf = malloc((size_t)size + 1); 322d5ac70f0Sopenharmony_ci if (!buffer->buf) { 323d5ac70f0Sopenharmony_ci free(input); 324d5ac70f0Sopenharmony_ci free(buffer); 325d5ac70f0Sopenharmony_ci return -ENOMEM; 326d5ac70f0Sopenharmony_ci } 327d5ac70f0Sopenharmony_ci memcpy(buffer->buf, buf, (size_t) size); 328d5ac70f0Sopenharmony_ci buffer->buf[size] = 0; 329d5ac70f0Sopenharmony_ci buffer->ptr = buffer->buf; 330d5ac70f0Sopenharmony_ci buffer->size = size; 331d5ac70f0Sopenharmony_ci input->type = SND_INPUT_BUFFER; 332d5ac70f0Sopenharmony_ci input->ops = &snd_input_buffer_ops; 333d5ac70f0Sopenharmony_ci input->private_data = buffer; 334d5ac70f0Sopenharmony_ci *inputp = input; 335d5ac70f0Sopenharmony_ci return 0; 336d5ac70f0Sopenharmony_ci} 337d5ac70f0Sopenharmony_ci 338