ReactOS 0.4.16-dev-927-g467dec4
fgets.cpp
Go to the documentation of this file.
1//
2// fgets.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Functions that read a string from a file.
7//
9
10
11
12// Reads a string from a stream. This function reads a string, up to 'count - 1'
13// characters in length, or until a '\n', whichever is reached first. The string
14// is always null-terminated on return. The '\n' _is_ written to the string if
15// it is encountered before space is exhausted. If EOF is encountered immediately,
16// null is returned. If EOF is encountered after some characters are read, EOF
17// terminates input just as '\n' would.
18//
19// Returns null if the count is nonpositive or if EOF is encountered immediately.
20// Otherwise, returns the string.
21template <typename Character>
22_Success_(return != 0)
23static Character* __cdecl common_fgets(
24 _Out_writes_z_(count) Character* const string,
28{
29 typedef __acrt_stdio_char_traits<Character> stdio_traits;
30
31 _VALIDATE_RETURN(string != nullptr || count == 0, EINVAL, nullptr);
32 _VALIDATE_RETURN(count >= 0, EINVAL, nullptr);
33 _VALIDATE_RETURN(stream.valid(), EINVAL, nullptr);
34
35 if (count == 0)
36 return nullptr;
37
38 Character* return_value = nullptr;
39
40 _lock_file(stream.public_stream());
41 __try
42 {
43 if (!stdio_traits::validate_stream_is_ansi_if_required(stream.public_stream()))
44 __leave;
45
46 // Note that we start iterating at 1, so we read at most 'count - 1'
47 // characters from the stream, leaving room for the null terminator:
48 Character* it = string;
49 for (int i = 1; i != count; ++i)
50 {
51 int const c = stdio_traits::getc_nolock(stream.public_stream());
52 if (c == stdio_traits::eof)
53 {
54 // If we immediately reach EOF before reading any characters,
55 // the C Language Standard mandates that the input buffer should
56 // be left unmodified, so we return immediately, without writing
57 // anything to the buffer:
58 if (it == string)
59 __leave;
60
61 // Otherwise, when we reach EOF, we just need to stop iterating:
62 break;
63 }
64
65 // We stop reading when we reach a newline. We do copy the newline:
66 *it++ = static_cast<Character>(c);
67 if (static_cast<Character>(c) == '\n')
68 break;
69 }
70
71 *it = '\0';
72 return_value = string;
73 }
75 {
76 _unlock_file(stream.public_stream());
77 }
79
80 return return_value;
81}
82
83
84
85extern "C" char* __cdecl fgets(
86 char* const string,
87 int const count,
88 FILE* const stream
89 )
90{
91 return common_fgets(string, count, __crt_stdio_stream(stream));
92}
93
94extern "C" wchar_t* __cdecl fgetws(
95 wchar_t* const string,
96 int const count,
97 FILE* const stream
98 )
99{
100 return common_fgets(string, count, __crt_stdio_stream(stream));
101}
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
wchar_t *__cdecl fgetws(wchar_t *const string, int const count, FILE *const stream)
Definition: fgets.cpp:94
int const count
Definition: fgets.cpp:25
int const __crt_stdio_stream const stream throw()
Definition: fgets.cpp:27
char *__cdecl fgets(char *const string, int const count, FILE *const stream)
Definition: fgets.cpp:85
GLuint GLuint GLsizei count
Definition: gl.h:1545
const GLubyte * c
Definition: glext.h:8905
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_CRTIMP void __cdecl _unlock_file(_Inout_ FILE *_File)
_CRTIMP void __cdecl _lock_file(_Inout_ FILE *_File)
#define c
Definition: ke_i.h:80
char string[160]
Definition: util.h:11
#define _Out_writes_z_(s)
Definition: no_sal2.h:180
#define _Success_(c)
Definition: no_sal2.h:84
#define __try
Definition: pseh2_64.h:188
#define __leave
Definition: pseh2_64.h:192
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
Definition: parse.h:23
#define const
Definition: zconf.h:233