summaryrefslogtreecommitdiffstats
path: root/common/estream.h
blob: e3c28feffc327bf121092f50a410903f5de1b6be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
/* estream.h - Extended stream I/O Library
 * Copyright (C) 2004, 2005, 2006, 2007, 2010, 2011 g10 Code GmbH
 *
 * This file is part of Libestream.
 *
 * Libestream 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 2 of the License,
 * or (at your option) any later version.
 *
 * Libestream 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 Libestream; if not, see <http://www.gnu.org/licenses/>.
 *
 * ALTERNATIVELY, Libestream may be distributed under the terms of the
 * following license, in which case the provisions of this license are
 * required INSTEAD OF the GNU General Public License. If you wish to
 * allow use of your version of this file only under the terms of the
 * GNU General Public License, and not to allow others to use your
 * version of this file under the terms of the following license,
 * indicate your decision by deleting this paragraph and the license
 * below.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, and the entire permission notice in its entirety,
 *    including the disclaimer of warranties.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef ESTREAM_H
#define ESTREAM_H

#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>

/* To use this file with libraries the following macro is useful:

     #define _ESTREAM_EXT_SYM_PREFIX _foo_

       This prefixes all external symbols with "_foo_".

 */


#ifdef _ESTREAM_EXT_SYM_PREFIX
#ifndef _ESTREAM_PREFIX
#define _ESTREAM_PREFIX1(x,y)  x ## y
#define _ESTREAM_PREFIX2(x,y) _ESTREAM_PREFIX1(x,y)
#define _ESTREAM_PREFIX(x)    _ESTREAM_PREFIX2(_ESTREAM_EXT_SYM_PREFIX,x)
#endif /*_ESTREAM_PREFIX*/
#define es_fopen              _ESTREAM_PREFIX(es_fopen)
#define es_mopen              _ESTREAM_PREFIX(es_mopen)
#define es_fopenmem           _ESTREAM_PREFIX(es_fopenmem)
#define es_fopenmem_init      _ESTREAM_PREFIX(es_fopenmem_init)
#define es_fdopen             _ESTREAM_PREFIX(es_fdopen)
#define es_fdopen_nc          _ESTREAM_PREFIX(es_fdopen_nc)
#define es_sysopen            _ESTREAM_PREFIX(es_sysopen)
#define es_sysopen_nc         _ESTREAM_PREFIX(es_sysopen_nc)
#define es_fpopen             _ESTREAM_PREFIX(es_fpopen)
#define es_fpopen_nc          _ESTREAM_PREFIX(es_fpopen_nc)
#define _es_set_std_fd        _ESTREAM_PREFIX(_es_set_std_fd)
#define _es_get_std_stream    _ESTREAM_PREFIX(_es_get_std_stream)
#define es_freopen            _ESTREAM_PREFIX(es_freopen)
#define es_fopencookie        _ESTREAM_PREFIX(es_fopencookie)
#define es_fclose             _ESTREAM_PREFIX(es_fclose)
#define es_fclose_snatch      _ESTREAM_PREFIX(es_fclose_snatch)
#define es_onclose            _ESTREAM_PREFIX(es_onclose)
#define es_fileno             _ESTREAM_PREFIX(es_fileno)
#define es_fileno_unlocked    _ESTREAM_PREFIX(es_fileno_unlocked)
#define es_flockfile          _ESTREAM_PREFIX(es_flockfile)
#define es_ftrylockfile       _ESTREAM_PREFIX(es_ftrylockfile)
#define es_funlockfile        _ESTREAM_PREFIX(es_funlockfile)
#define es_feof               _ESTREAM_PREFIX(es_feof)
#define es_feof_unlocked      _ESTREAM_PREFIX(es_feof_unlocked)
#define es_ferror             _ESTREAM_PREFIX(es_ferror)
#define es_ferror_unlocked    _ESTREAM_PREFIX(es_ferror_unlocked)
#define es_clearerr           _ESTREAM_PREFIX(es_clearerr)
#define es_clearerr_unlocked  _ESTREAM_PREFIX(es_clearerr_unlocked)
#define es_fflush             _ESTREAM_PREFIX(es_fflush)
#define es_fseek              _ESTREAM_PREFIX(es_fseek)
#define es_fseeko             _ESTREAM_PREFIX(es_fseeko)
#define es_ftell              _ESTREAM_PREFIX(es_ftell)
#define es_ftello             _ESTREAM_PREFIX(es_ftello)
#define es_rewind             _ESTREAM_PREFIX(es_rewind)
#define es_fgetc              _ESTREAM_PREFIX(es_fgetc)
#define es_fputc              _ESTREAM_PREFIX(es_fputc)
#define _es_getc_underflow    _ESTREAM_PREFIX(_es_getc_underflow)
#define _es_putc_overflow     _ESTREAM_PREFIX(_es_putc_overflow)
#define es_ungetc             _ESTREAM_PREFIX(es_ungetc)
#define es_read               _ESTREAM_PREFIX(es_read)
#define es_write              _ESTREAM_PREFIX(es_write)
#define es_write_sanitized    _ESTREAM_PREFIX(es_write_sanitized)
#define es_write_hexstring    _ESTREAM_PREFIX(es_write_hexstring)
#define es_fread              _ESTREAM_PREFIX(es_fread)
#define es_fwrite             _ESTREAM_PREFIX(es_fwrite)
#define es_fgets              _ESTREAM_PREFIX(es_fgets)
#define es_fputs              _ESTREAM_PREFIX(es_fputs)
#define es_fputs_unlocked     _ESTREAM_PREFIX(es_fputs_unlocked)
#define es_getline            _ESTREAM_PREFIX(es_getline)
#define es_read_line          _ESTREAM_PREFIX(es_read_line)
#define es_free               _ESTREAM_PREFIX(es_free)
#define es_fprintf            _ESTREAM_PREFIX(es_fprintf)
#define es_fprintf_unlocked   _ESTREAM_PREFIX(es_fprintf_unlocked)
#define es_printf             _ESTREAM_PREFIX(es_printf)
#define es_printf_unlocked    _ESTREAM_PREFIX(es_printf_unlocked)
#define es_vfprintf           _ESTREAM_PREFIX(es_vfprint)
#define es_vfprintf_unlocked  _ESTREAM_PREFIX(es_vfprint_unlocked)
#define es_setvbuf            _ESTREAM_PREFIX(es_setvbuf)
#define es_setbuf             _ESTREAM_PREFIX(es_setbuf)
#define es_set_binary         _ESTREAM_PREFIX(es_set_binary)
#define es_tmpfile            _ESTREAM_PREFIX(es_tmpfile)
#define es_opaque_set         _ESTREAM_PREFIX(es_opaque_set)
#define es_opaque_get         _ESTREAM_PREFIX(es_opaque_get)
#define es_fname_set          _ESTREAM_PREFIX(es_fname_set)
#define es_fname_get          _ESTREAM_PREFIX(es_fname_get)
#define es_write_sanitized_utf8_buffer  \
              _ESTREAM_PREFIX(es_write_sanitized_utf8_buffer)
#endif /*_ESTREAM_EXT_SYM_PREFIX*/


#ifdef __cplusplus
extern "C"
{
#if 0
}
#endif
#endif


/* Forward declaration for the (opaque) internal type.  */
struct estream_internal;

/* The definition of this struct is entirely private.  You must not
   use it for anything.  It is only here so some functions can be
   implemented as macros.  */
struct es__stream
{
  /* The layout of this struct must never change.  It may be grown,
     but only if all functions which access the new members are
     versioned.  */

  /* A pointer to the stream buffer.  */
  unsigned char *buffer;

  /* The size of the buffer in bytes.  */
  size_t buffer_size;

  /* The length of the usable data in the buffer, only valid when in
     read mode (see flags).  */
  size_t data_len;

  /* The current position of the offset pointer, valid in read and
     write mode.  */
  size_t data_offset;

  size_t data_flushed;
  unsigned char *unread_buffer;
  size_t unread_buffer_size;

  /* The number of unread bytes.  */
  size_t unread_data_len;

  /* Various flags.  */
  struct {
    unsigned int writing: 1;
    unsigned int reserved: 7;
  } flags;

  /* A pointer to our internal data for this stream.  */
  struct estream_internal *intern;
};

/* The opaque type for an estream.  */
typedef struct es__stream *estream_t;


typedef ssize_t (*es_cookie_read_function_t) (void *cookie,
					      void *buffer, size_t size);
typedef ssize_t (*es_cookie_write_function_t) (void *cookie,
					       const void *buffer,
					       size_t size);
typedef int (*es_cookie_seek_function_t) (void *cookie,
					  off_t *pos, int whence);
typedef int (*es_cookie_close_function_t) (void *cookie);

typedef struct es_cookie_io_functions
{
  es_cookie_read_function_t func_read;
  es_cookie_write_function_t func_write;
  es_cookie_seek_function_t func_seek;
  es_cookie_close_function_t func_close;
} es_cookie_io_functions_t;


enum es_syshd_types
  {
    ES_SYSHD_NONE,  /* No system handle available.  */
    ES_SYSHD_FD,    /* A file descriptor as returned by open().  */
    ES_SYSHD_SOCK,  /* A socket as returned by socket().        */
    ES_SYSHD_RVID,  /* A rendevous id (see libassuan's gpgcedev.c).  */
    ES_SYSHD_HANDLE /* A HANDLE object (Windows).  */
  };

typedef struct
{
  enum es_syshd_types type;
  union {
    int fd;
    int sock;
    int rvid;
    void *handle;
  } u;
} es_syshd_t;




#ifndef _ESTREAM_GCC_A_PRINTF
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
# define _ESTREAM_GCC_A_PRINTF( f, a )  __attribute__ ((format (printf,f,a)))
#else
# define _ESTREAM_GCC_A_PRINTF( f, a )
#endif
#endif /*_ESTREAM_GCC_A_PRINTF*/


#ifndef ES__RESTRICT
#  if defined __GNUC__ && defined __GNUC_MINOR__
#    if  (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 92))
#      define ES__RESTRICT __restrict__
#    endif
#  endif
#endif
#ifndef ES__RESTRICT
#  define ES__RESTRICT
#endif

int es_init (void);

estream_t es_fopen (const char *ES__RESTRICT path,
		    const char *ES__RESTRICT mode);
estream_t es_mopen (void *ES__RESTRICT data,
		    size_t data_n, size_t data_len,
		    unsigned int grow,
		    void *(*func_realloc) (void *mem, size_t size),
		    void (*func_free) (void *mem),
		    const char *ES__RESTRICT mode);
estream_t es_fopenmem (size_t memlimit, const char *ES__RESTRICT mode);
estream_t es_fopenmem_init (size_t memlimit, const char *ES__RESTRICT mode,
                            const void *data, size_t datalen);
estream_t es_fdopen (int filedes, const char *mode);
estream_t es_fdopen_nc (int filedes, const char *mode);
estream_t es_sysopen (es_syshd_t *syshd, const char *mode);
estream_t es_sysopen_nc (es_syshd_t *syshd, const char *mode);
estream_t es_fpopen (FILE *fp, const char *mode);
estream_t es_fpopen_nc (FILE *fp, const char *mode);
estream_t es_freopen (const char *ES__RESTRICT path,
		      const char *ES__RESTRICT mode,
		      estream_t ES__RESTRICT stream);
estream_t es_fopencookie (void *ES__RESTRICT cookie,
			  const char *ES__RESTRICT mode,
			  es_cookie_io_functions_t functions);
int es_fclose (estream_t stream);
int es_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen);
int es_onclose (estream_t stream, int mode,
                void (*fnc) (estream_t, void*), void *fnc_value);
int es_fileno (estream_t stream);
int es_fileno_unlocked (estream_t stream);
int es_syshd (estream_t stream, es_syshd_t *syshd);
int es_syshd_unlocked (estream_t stream, es_syshd_t *syshd);

void _es_set_std_fd (int no, int fd);
estream_t _es_get_std_stream (int fd);

#define es_stdin  _es_get_std_stream (0)
#define es_stdout _es_get_std_stream (1)
#define es_stderr _es_get_std_stream (2)


void es_flockfile (estream_t stream);
int es_ftrylockfile (estream_t stream);
void es_funlockfile (estream_t stream);

int es_feof (estream_t stream);
int es_feof_unlocked (estream_t stream);
int es_ferror (estream_t stream);
int es_ferror_unlocked (estream_t stream);
void es_clearerr (estream_t stream);
void es_clearerr_unlocked (estream_t stream);

int es_fflush (estream_t stream);
int es_fseek (estream_t stream, long int offset, int whence);
int es_fseeko (estream_t stream, off_t offset, int whence);
long int es_ftell (estream_t stream);
off_t es_ftello (estream_t stream);
void es_rewind (estream_t stream);

int es_fgetc (estream_t stream);
int es_fputc (int c, estream_t stream);

int _es_getc_underflow (estream_t stream);
int _es_putc_overflow (int c, estream_t stream);

#define es_getc_unlocked(stream)				\
  (((!(stream)->flags.writing)					\
    && ((stream)->data_offset < (stream)->data_len)		\
    && (! (stream)->unread_data_len))				\
  ? ((int) (stream)->buffer[((stream)->data_offset)++])		\
  : _es_getc_underflow ((stream)))

#define es_putc_unlocked(c, stream)				\
  (((stream)->flags.writing					\
    && ((stream)->data_offset < (stream)->buffer_size)		\
    && (c != '\n'))						\
  ? ((int) ((stream)->buffer[((stream)->data_offset)++] = (c)))	\
  : _es_putc_overflow ((c), (stream)))

#define es_getc(stream)    es_fgetc (stream)
#define es_putc(c, stream) es_fputc (c, stream)

int es_ungetc (int c, estream_t stream);

int es_read (estream_t ES__RESTRICT stream,
	     void *ES__RESTRICT buffer, size_t bytes_to_read,
	     size_t *ES__RESTRICT bytes_read);
int es_write (estream_t ES__RESTRICT stream,
	      const void *ES__RESTRICT buffer, size_t bytes_to_write,
	      size_t *ES__RESTRICT bytes_written);
int es_write_sanitized (estream_t ES__RESTRICT stream,
                        const void *ES__RESTRICT buffer, size_t length,
                        const char *delimiters,
                        size_t *ES__RESTRICT bytes_written);
int es_write_hexstring (estream_t ES__RESTRICT stream,
                        const void *ES__RESTRICT buffer, size_t length,
                        int reserved, size_t *ES__RESTRICT bytes_written);

size_t es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems,
		 estream_t ES__RESTRICT stream);
size_t es_fwrite (const void *ES__RESTRICT ptr, size_t size, size_t memb,
		  estream_t ES__RESTRICT stream);

char *es_fgets (char *ES__RESTRICT s, int n, estream_t ES__RESTRICT stream);
int es_fputs (const char *ES__RESTRICT s, estream_t ES__RESTRICT stream);
int es_fputs_unlocked (const char *ES__RESTRICT s,
                       estream_t ES__RESTRICT stream);

ssize_t es_getline (char *ES__RESTRICT *ES__RESTRICT lineptr,
		    size_t *ES__RESTRICT n,
		    estream_t stream);
ssize_t es_read_line (estream_t stream,
                      char **addr_of_buffer, size_t *length_of_buffer,
                      size_t *max_length);
void es_free (void *a);

int es_fprintf (estream_t ES__RESTRICT stream,
		const char *ES__RESTRICT format, ...)
     _ESTREAM_GCC_A_PRINTF(2,3);
int es_fprintf_unlocked (estream_t ES__RESTRICT stream,
                         const char *ES__RESTRICT format, ...)
     _ESTREAM_GCC_A_PRINTF(2,3);

int es_printf (const char *ES__RESTRICT format, ...)
     _ESTREAM_GCC_A_PRINTF(1,2);
int es_printf_unlocked (const char *ES__RESTRICT format, ...)
     _ESTREAM_GCC_A_PRINTF(1,2);

int es_vfprintf (estream_t ES__RESTRICT stream,
		 const char *ES__RESTRICT format, va_list ap)
     _ESTREAM_GCC_A_PRINTF(2,0);
int es_vfprintf_unlocked (estream_t ES__RESTRICT stream,
                          const char *ES__RESTRICT format, va_list ap)
     _ESTREAM_GCC_A_PRINTF(2,0);

char *es_asprintf (const char *ES__RESTRICT format, ...)
     _ESTREAM_GCC_A_PRINTF(1,2);
char *es_vasprintf (const char *ES__RESTRICT format, va_list ap)
     _ESTREAM_GCC_A_PRINTF(1,0);

int es_setvbuf (estream_t ES__RESTRICT stream,
		char *ES__RESTRICT buf, int mode, size_t size);
void es_setbuf (estream_t ES__RESTRICT stream, char *ES__RESTRICT buf);

void es_set_binary (estream_t stream);


estream_t es_tmpfile (void);

void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque);
void *es_opaque_get (estream_t stream);

void es_fname_set (estream_t stream, const char *fname);
const char *es_fname_get (estream_t stream);


#ifdef GNUPG_MAJOR_VERSION
int es_write_sanitized_utf8_buffer (estream_t stream,
                                    const void *buffer, size_t length,
                                    const char *delimiters,
                                    size_t *bytes_written);
#endif /*GNUPG_MAJOR_VERSION*/

#ifdef __cplusplus
}
#endif
#endif /*ESTREAM_H*/