8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sort / common / streams_wide.c
blob33990022779fe716596525e8309e2d8a1195a153
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include "streams_wide.h"
29 #include "streams_common.h"
31 #define WIDE_VBUF_SIZE (64 * KILOBYTE)
33 #define SHELF_OCCUPIED 1
34 #define SHELF_VACANT 0
35 static int shelf = SHELF_VACANT;
38 * Wide character streams implementation
40 * The wide character streams implementation is, for the most part, a
41 * reimplementation of the stdio streams implementation, using wide character
42 * string routines. However, fgetws(3C) retains the newline that fgets(3C)
43 * discards while reading a complete line. As a result, the wide character
44 * routines need to guard against coincidental exhaustion of the buffer, as
45 * well as overwriting the end-of-line character and correcting the
46 * l_data_length field.
49 static int
50 stream_wide_prime(stream_t *str)
52 stream_buffered_file_t *BF = &(str->s_type.BF);
53 wchar_t *current_position;
54 wchar_t *end_of_buffer;
55 wchar_t *next_nl;
57 ASSERT(!(str->s_status & STREAM_OUTPUT));
58 ASSERT(str->s_status & STREAM_OPEN);
60 if (str->s_status & STREAM_INSTANT && (str->s_buffer == NULL)) {
61 str->s_buffer = xzmap(0, WIDE_VBUF_SIZE, PROT_READ |
62 PROT_WRITE, MAP_PRIVATE, 0);
63 if (str->s_buffer == MAP_FAILED)
64 die(EMSG_MMAP);
65 str->s_buffer_size = WIDE_VBUF_SIZE;
68 ASSERT(str->s_buffer != NULL);
70 if (stream_is_primed(str)) {
71 int shelf_state = shelf;
73 ASSERT(str->s_current.l_data_length >= -1);
74 (void) memcpy(str->s_buffer, str->s_current.l_data.wp,
75 (str->s_current.l_data_length + 1) * sizeof (wchar_t));
76 str->s_current.l_data.wp = str->s_buffer;
78 if ((str->s_current.l_data_length == -1 ||
79 shelf_state == SHELF_OCCUPIED ||
80 *(str->s_current.l_data.wp +
81 str->s_current.l_data_length) != L'\0') &&
82 SOP_FETCH(str) == NEXT_LINE_INCOMPLETE &&
83 shelf_state == SHELF_OCCUPIED)
84 die(EMSG_MEMORY);
86 return (PRIME_SUCCEEDED);
89 stream_set(str, STREAM_PRIMED);
91 current_position = (wchar_t *)str->s_buffer;
92 /*LINTED ALIGNMENT*/
93 end_of_buffer = (wchar_t *)((char *)str->s_buffer +
94 str->s_buffer_size);
96 trip_eof(BF->s_fp);
97 if (!feof(BF->s_fp))
98 (void) fgetws(current_position, end_of_buffer
99 - current_position, BF->s_fp);
100 else {
101 stream_set(str, STREAM_EOS_REACHED);
102 stream_unset(str, STREAM_PRIMED);
103 return (PRIME_FAILED_EMPTY_FILE);
106 str->s_current.l_data.wp = current_position;
107 next_nl = xmemwchar(current_position, L'\n', end_of_buffer -
108 current_position);
109 if (next_nl == NULL) {
110 warn(WMSG_NEWLINE_ADDED, str->s_filename);
111 str->s_current.l_data_length = MIN(wslen(current_position),
112 end_of_buffer - current_position);
113 } else {
114 str->s_current.l_data_length = next_nl - current_position;
116 *(str->s_current.l_data.wp + str->s_current.l_data_length) = L'\0';
118 str->s_current.l_collate.wp = NULL;
119 str->s_current.l_collate_length = 0;
121 __S(stats_incr_fetches());
122 return (PRIME_SUCCEEDED);
125 static ssize_t
126 stream_wide_fetch(stream_t *str)
128 ssize_t dist_to_buf_end;
129 int ret_val;
130 wchar_t *graft_pt;
131 wchar_t *next_nl;
133 ASSERT(str->s_status & STREAM_OPEN);
134 ASSERT((str->s_status & STREAM_EOS_REACHED) == 0);
136 graft_pt = str->s_current.l_data.wp + str->s_current.l_data_length + 1;
138 if (shelf == SHELF_VACANT)
139 str->s_current.l_data.wp = graft_pt;
140 else if (str->s_current.l_data_length > -1)
141 graft_pt--;
143 dist_to_buf_end = str->s_buffer_size / sizeof (wchar_t) - (graft_pt -
144 (wchar_t *)str->s_buffer);
146 if (dist_to_buf_end <= 1) {
147 str->s_current.l_data_length = -1;
148 return (NEXT_LINE_INCOMPLETE);
151 if (fgetws(graft_pt, dist_to_buf_end, str->s_type.BF.s_fp) == NULL) {
152 if (feof(str->s_type.BF.s_fp))
153 stream_set(str, STREAM_EOS_REACHED);
154 else
155 die(EMSG_READ, str->s_filename);
158 trip_eof(str->s_type.BF.s_fp);
159 if ((next_nl = xmemwchar(str->s_current.l_data.wp, L'\n',
160 dist_to_buf_end)) == NULL) {
161 str->s_current.l_data_length =
162 MIN(wslen(str->s_current.l_data.wp), dist_to_buf_end);
163 } else {
164 str->s_current.l_data_length = next_nl -
165 str->s_current.l_data.wp;
168 str->s_current.l_collate_length = 0;
170 if (*(str->s_current.l_data.wp + str->s_current.l_data_length) !=
171 L'\n') {
172 if (!feof(str->s_type.BF.s_fp)) {
173 if (shelf == SHELF_OCCUPIED)
174 die(EMSG_MEMORY);
176 shelf = SHELF_OCCUPIED;
177 ret_val = NEXT_LINE_INCOMPLETE;
178 __S(stats_incr_shelves());
179 } else {
180 stream_set(str, STREAM_EOS_REACHED);
181 warn(WMSG_NEWLINE_ADDED, str->s_filename);
183 } else {
184 shelf = SHELF_VACANT;
185 ret_val = NEXT_LINE_COMPLETE;
186 *(str->s_current.l_data.wp + str->s_current.l_data_length) =
187 L'\0';
188 __S(stats_incr_fetches());
191 return (ret_val);
194 ssize_t
195 stream_wide_fetch_overwrite(stream_t *str)
197 ssize_t dist_to_buf_end;
199 ASSERT(str->s_status & STREAM_OPEN);
200 ASSERT((str->s_status & STREAM_EOS_REACHED) == 0);
202 str->s_current.l_data.wp = str->s_buffer;
203 dist_to_buf_end = str->s_buffer_size / sizeof (wchar_t);
205 if (fgetws(str->s_current.l_data.wp, dist_to_buf_end,
206 str->s_type.BF.s_fp) == NULL) {
207 if (feof(str->s_type.BF.s_fp))
208 stream_set(str, STREAM_EOS_REACHED);
209 else
210 die(EMSG_READ, str->s_filename);
213 trip_eof(str->s_type.BF.s_fp);
214 str->s_current.l_data_length = wslen(str->s_current.l_data.wp) - 1;
215 str->s_current.l_collate_length = 0;
217 if (str->s_current.l_data_length == -1 ||
218 *(str->s_current.l_data.wp + str->s_current.l_data_length) !=
219 L'\n') {
220 if (!feof(str->s_type.BF.s_fp)) {
221 die(EMSG_MEMORY);
222 } else {
223 stream_set(str, STREAM_EOS_REACHED);
224 warn(WMSG_NEWLINE_ADDED, str->s_filename);
225 str->s_current.l_data_length++;
229 *(str->s_current.l_data.wp + str->s_current.l_data_length) = L'\0';
231 __S(stats_incr_fetches());
232 return (NEXT_LINE_COMPLETE);
235 static void
236 stream_wide_send_eol(stream_t *str)
238 wchar_t w_crlf[2] = { L'\n', L'\0' };
240 ASSERT(str->s_status & STREAM_OPEN);
241 ASSERT(str->s_status & STREAM_OUTPUT);
243 if (wxwrite(str->s_type.SF.s_fd, w_crlf) < 0)
244 die(EMSG_WRITE, str->s_filename);
247 static void
248 stream_wide_put_line(stream_t *str, line_rec_t *line)
250 ASSERT(str->s_status & STREAM_OPEN);
251 ASSERT(str->s_status & STREAM_OUTPUT);
253 if (line->l_data_length >= 0) {
254 if (wxwrite(str->s_type.SF.s_fd, line->l_data.wp) >= 0) {
255 stream_wide_send_eol(str);
256 __S(stats_incr_puts());
257 } else
258 die(EMSG_WRITE, str->s_filename);
260 safe_free(line->l_raw_collate.wp);
261 line->l_raw_collate.wp = NULL;
264 void
265 stream_wide_put_line_unique(stream_t *str, line_rec_t *line)
267 static line_rec_t pvs;
268 static size_t collate_buf_len;
270 ASSERT(str->s_status & STREAM_OPEN);
271 ASSERT(str->s_status & STREAM_OUTPUT);
273 if ((pvs.l_collate.sp == NULL ||
274 collated_wide(&pvs, line, 0, COLL_UNIQUE) != 0) &&
275 line->l_data_length >= 0) {
276 stream_wide_put_line(str, line);
278 if (line->l_collate_length + sizeof (wchar_t) >
279 collate_buf_len) {
280 pvs.l_collate.sp = safe_realloc(pvs.l_collate.sp,
281 line->l_collate_length + sizeof (wchar_t));
282 collate_buf_len = line->l_collate_length +
283 sizeof (wchar_t);
286 (void) memcpy(pvs.l_collate.sp, line->l_collate.sp,
287 line->l_collate_length);
288 /* LINTED ALIGNMENT */
289 *(wchar_t *)(pvs.l_collate.sp + line->l_collate_length) = L'\0';
290 pvs.l_collate_length = line->l_collate_length;
294 static int
295 stream_wide_eos(stream_t *str)
297 int retval = 0;
299 if (str == NULL || str->s_status & STREAM_EOS_REACHED)
300 return (1);
302 trip_eof(str->s_type.BF.s_fp);
303 if (feof(str->s_type.BF.s_fp) &&
304 shelf == SHELF_VACANT &&
305 str->s_current.l_collate_length != -1) {
306 retval = 1;
307 stream_set(str, STREAM_EOS_REACHED);
310 return (retval);
313 /*ARGSUSED*/
314 static void
315 stream_wide_release_line(stream_t *str)
319 const stream_ops_t stream_wide_ops = {
320 stream_stdio_is_closable,
321 stream_stdio_close,
322 stream_wide_eos,
323 stream_wide_fetch,
324 stream_stdio_flush,
325 stream_stdio_free,
326 stream_stdio_open_for_write,
327 stream_wide_prime,
328 stream_wide_put_line,
329 stream_wide_release_line,
330 stream_wide_send_eol,
331 stream_stdio_unlink