GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/stdio/open_wmemstream.c Lines: 0 68 0.0 %
Date: 2017-11-07 Branches: 0 33 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: open_wmemstream.c,v 1.8 2015/09/12 16:23:14 guenther Exp $	*/
2
3
/*
4
 * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <errno.h>
20
#include <fcntl.h>
21
#include <stdio.h>
22
#include <stdint.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <wchar.h>
26
#include "local.h"
27
28
#define	MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
29
30
struct state {
31
	wchar_t		 *string;	/* actual stream */
32
	wchar_t		**pbuf;		/* point to the stream */
33
	size_t		 *psize;	/* point to min(pos, len) */
34
	size_t		  pos;		/* current position */
35
	size_t		  size;		/* number of allocated wchar_t */
36
	size_t		  len;		/* length of the data */
37
	mbstate_t	  mbs;		/* conversion state of the stream */
38
};
39
40
static int
41
wmemstream_write(void *v, const char *b, int l)
42
{
43
	struct state	*st = v;
44
	wchar_t		*p;
45
	size_t		 nmc, len, end;
46
47
	end = (st->pos + l);
48
49
	if (end >= st->size) {
50
		/* 1.6 is (very) close to the golden ratio. */
51
		size_t	sz = st->size * 8 / 5;
52
53
		if (sz < end + 1)
54
			sz = end + 1;
55
		p = reallocarray(st->string, sz, sizeof(wchar_t));
56
		if (!p)
57
			return (-1);
58
		bzero(p + st->size, (sz - st->size) * sizeof(wchar_t));
59
		*st->pbuf = st->string = p;
60
		st->size = sz;
61
	}
62
63
	nmc = (st->size - st->pos) * sizeof(wchar_t);
64
	len = mbsnrtowcs(st->string + st->pos, &b, nmc, l, &st->mbs);
65
	if (len == (size_t)-1)
66
		return (-1);
67
	st->pos += len;
68
69
	if (st->pos > st->len) {
70
		st->len = st->pos;
71
		st->string[st->len] = L'\0';
72
	}
73
74
	*st->psize = st->pos;
75
76
	return (len);
77
}
78
79
static fpos_t
80
wmemstream_seek(void *v, fpos_t off, int whence)
81
{
82
	struct state	*st = v;
83
	ssize_t		 base = 0;
84
85
	switch (whence) {
86
	case SEEK_SET:
87
		break;
88
	case SEEK_CUR:
89
		base = st->pos;
90
		break;
91
	case SEEK_END:
92
		base = st->len;
93
		break;
94
	}
95
96
	if (off > (SIZE_MAX / sizeof(wchar_t)) - base || off < -base) {
97
		errno = EOVERFLOW;
98
		return (-1);
99
	}
100
101
	/*
102
	 * XXX Clearing mbs here invalidates shift state for state-
103
	 * dependent encodings, but they are not (yet) supported.
104
	 */
105
	bzero(&st->mbs, sizeof(st->mbs));
106
107
	st->pos = base + off;
108
	*st->psize = MINIMUM(st->pos, st->len);
109
110
	return (st->pos);
111
}
112
113
static int
114
wmemstream_close(void *v)
115
{
116
	struct state	*st = v;
117
118
	free(st);
119
120
	return (0);
121
}
122
123
FILE *
124
open_wmemstream(wchar_t **pbuf, size_t *psize)
125
{
126
	struct state	*st;
127
	FILE		*fp;
128
129
	if (pbuf == NULL || psize == NULL) {
130
		errno = EINVAL;
131
		return (NULL);
132
	}
133
134
	if ((st = malloc(sizeof(*st))) == NULL)
135
		return (NULL);
136
137
	if ((fp = __sfp()) == NULL) {
138
		free(st);
139
		return (NULL);
140
	}
141
142
	st->size = BUFSIZ * sizeof(wchar_t);
143
	if ((st->string = calloc(1, st->size)) == NULL) {
144
		free(st);
145
		fp->_flags = 0;
146
		return (NULL);
147
	}
148
149
	*st->string = L'\0';
150
	st->pos = 0;
151
	st->len = 0;
152
	st->pbuf = pbuf;
153
	st->psize = psize;
154
	bzero(&st->mbs, sizeof(st->mbs));
155
156
	*pbuf = st->string;
157
	*psize = st->len;
158
159
	fp->_flags = __SWR;
160
	fp->_file = -1;
161
	fp->_cookie = st;
162
	fp->_read = NULL;
163
	fp->_write = wmemstream_write;
164
	fp->_seek = wmemstream_seek;
165
	fp->_close = wmemstream_close;
166
	_SET_ORIENTATION(fp, 1);
167
168
	return (fp);
169
}