ReactOS 0.4.16-dev-959-g2ec3a19
ungetc.cpp
Go to the documentation of this file.
1//
2// ungetc.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines ungetc(), which pushes a character back into a stream.
7//
9
10
11
12// Pushes a character ("ungets" it) back into a stream. It is possible to push
13// back one character. It may not be possible to push back more than one
14// character in a row. Returns the pushed-back character on success; returns
15// EOF on failure. Ungetting EOF is expressly forbidden.
16extern "C" int __cdecl ungetc(int const c, FILE* const stream)
17{
18 _VALIDATE_RETURN(stream != nullptr, EINVAL, EOF);
19
20 int return_value = EOF;
21
23 __try
24 {
25 return_value = _ungetc_nolock(c, stream);
26 }
28 {
30 }
32
33 return return_value;
34}
35
36
37
38extern "C" int __cdecl _ungetc_nolock(int const c, FILE* public_stream)
39{
40 __crt_stdio_stream const stream(public_stream);
41
43
44 // Ungetting EOF is expressly forbidden:
45 if (c == EOF)
46 return EOF;
47
48 // The stream must either be open in read-only mode, or must be open in
49 // read-write mode and must not currently be in write mode:
50 bool const is_in_read_only_mode = stream.has_all_of(_IOREAD);
51 bool const is_in_rw_write_mode = stream.has_all_of(_IOUPDATE | _IOWRITE);
52
53 if (!is_in_read_only_mode && !is_in_rw_write_mode)
54 return EOF;
55
56 // If the stream is currently unbuffered, buffer it:
57 if (stream->_base == nullptr)
59
60 // At this point, we know that _base is not null, since the file is buffered.
61
62 if (stream->_ptr == stream->_base)
63 {
64 // If we've already buffered a pushed-back character, there's no room for
65 // another, and there's nothing we can do:
66 if (stream->_cnt)
67 return EOF;
68
69 ++stream->_ptr;
70 }
71
72 // If the stream is string-backed (and not file-backed), do not modify the buffer:
73 if (stream.is_string_backed())
74 {
75 --stream->_ptr;
76 if (*stream->_ptr != static_cast<char>(c))
77 {
78 ++stream->_ptr;
79 return EOF;
80 }
81 }
82 else
83 {
84 --stream->_ptr;
85 *stream->_ptr = static_cast<char>(c);
86 }
87
88 ++stream->_cnt;
89 stream.unset_flags(_IOEOF);
90 stream.set_flags(_IOREAD);
91
92 return c & 0xff;
93}
void __cdecl __acrt_stdio_allocate_buffer_nolock(FILE *const public_stream)
Definition: _getbuf.cpp:16
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
#define _VALIDATE_STREAM_ANSI_RETURN(stream, errorcode, retexpr)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
const GLubyte * c
Definition: glext.h:8905
#define EOF
Definition: stdio.h:24
_CRTIMP void __cdecl _unlock_file(_Inout_ FILE *_File)
#define _IOEOF
Definition: stdio.h:132
#define _IOREAD
Definition: stdio.h:124
_CRTIMP void __cdecl _lock_file(_Inout_ FILE *_File)
#define c
Definition: ke_i.h:80
#define __try
Definition: pseh2_64.h:188
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
Definition: parse.h:23
int __cdecl _ungetc_nolock(int const c, FILE *public_stream)
Definition: ungetc.cpp:38
int __cdecl ungetc(int const c, FILE *const stream)
Definition: ungetc.cpp:16