Finish <stdio_ext.h>.
Implement __freading and __fwriting, and clarify the documentation that was the cause of these not being implemented for years. Bug: http://b/17157253 Test: ran tests Change-Id: I89542c8131b13889e2585417a024050ecf2abcb7
This commit is contained in:
parent
1bac61f09f
commit
5ba2c21159
11 changed files with 85 additions and 14 deletions
|
@ -40,7 +40,9 @@ __BEGIN_DECLS
|
|||
|
||||
size_t __fbufsize(FILE*) __INTRODUCED_IN(23);
|
||||
int __freadable(FILE*) __INTRODUCED_IN(23);
|
||||
int __freading(FILE*) __INTRODUCED_IN_FUTURE;
|
||||
int __fwritable(FILE*) __INTRODUCED_IN(23);
|
||||
int __fwriting(FILE*) __INTRODUCED_IN_FUTURE;
|
||||
int __flbf(FILE*) __INTRODUCED_IN(23);
|
||||
void __fpurge(FILE*) __INTRODUCED_IN(23);
|
||||
size_t __fpending(FILE*) __INTRODUCED_IN(23);
|
||||
|
|
|
@ -1320,6 +1320,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1240,6 +1240,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1345,6 +1345,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1304,6 +1304,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1240,6 +1240,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1302,6 +1302,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -1240,6 +1240,8 @@ LIBC_O {
|
|||
|
||||
LIBC_P {
|
||||
global:
|
||||
__freading; # future
|
||||
__fwriting; # future
|
||||
getlogin_r; # future
|
||||
} LIBC_O;
|
||||
|
||||
|
|
|
@ -127,10 +127,11 @@ struct __sfileext {
|
|||
// Values for `__sFILE::_flags`.
|
||||
#define __SLBF 0x0001 // Line buffered.
|
||||
#define __SNBF 0x0002 // Unbuffered.
|
||||
// RD and WR are never simultaneously asserted: use _SRW instead.
|
||||
#define __SRD 0x0004 // OK to read.
|
||||
#define __SWR 0x0008 // OK to write.
|
||||
#define __SRW 0x0010 // Open for reading & writing.
|
||||
// __SRD and __SWR are mutually exclusive because they indicate what we did last.
|
||||
// If you want to know whether we were opened read-write, check __SRW instead.
|
||||
#define __SRD 0x0004 // Last operation was read.
|
||||
#define __SWR 0x0008 // Last operation was write.
|
||||
#define __SRW 0x0010 // Was opened for reading & writing.
|
||||
#define __SEOF 0x0020 // Found EOF.
|
||||
#define __SERR 0x0040 // Found error.
|
||||
#define __SMBF 0x0080 // `_buf` is from malloc.
|
||||
|
|
|
@ -39,17 +39,13 @@ size_t __fbufsize(FILE* fp) {
|
|||
return fp->_bf._size;
|
||||
}
|
||||
|
||||
/* For a _SRW stream, we don't know whether we last read or wrote.
|
||||
int __freading(FILE* fp) {
|
||||
return (fp->_flags & _SRD) != 0 || ...;
|
||||
return (fp->_flags & __SRD) != 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* For a _SRW stream, we don't know whether we last read or wrote.
|
||||
int __fwriting(FILE*) {
|
||||
return (fp->_flags & _SWR) != 0 || ...;
|
||||
int __fwriting(FILE* fp) {
|
||||
return (fp->_flags & __SWR) != 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int __freadable(FILE* fp) {
|
||||
return (fp->_flags & (__SRD|__SRW)) != 0;
|
||||
|
|
|
@ -116,20 +116,78 @@ TEST(stdio_ext, _flushlbf) {
|
|||
}
|
||||
|
||||
TEST(stdio_ext, __freadable__fwritable) {
|
||||
FILE* fp = fopen("/dev/null", "r");
|
||||
FILE* fp;
|
||||
|
||||
// Read-only.
|
||||
fp = fopen("/dev/null", "r");
|
||||
ASSERT_TRUE(__freadable(fp));
|
||||
ASSERT_FALSE(__fwritable(fp));
|
||||
fclose(fp);
|
||||
|
||||
// Write-only.
|
||||
fp = fopen("/dev/null", "w");
|
||||
ASSERT_FALSE(__freadable(fp));
|
||||
ASSERT_TRUE(__fwritable(fp));
|
||||
fclose(fp);
|
||||
|
||||
fp = fopen("/dev/null", "w+");
|
||||
// Append (aka write-only).
|
||||
fp = fopen("/dev/null", "a");
|
||||
ASSERT_FALSE(__freadable(fp));
|
||||
ASSERT_TRUE(__fwritable(fp));
|
||||
fclose(fp);
|
||||
|
||||
// The three read-write modes.
|
||||
for (auto read_write_mode : {"r+", "w+", "a+"}) {
|
||||
fp = fopen("/dev/null", read_write_mode);
|
||||
ASSERT_TRUE(__freadable(fp));
|
||||
ASSERT_TRUE(__fwritable(fp));
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(stdio_ext, __freading__fwriting) {
|
||||
FILE* fp;
|
||||
|
||||
// Append (aka write-only). Never reading. Always writing.
|
||||
fp = fopen("/dev/zero", "a");
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading initially.
|
||||
ASSERT_TRUE(__fwriting(fp)); // Writing initially.
|
||||
ASSERT_TRUE(fputc('x', fp) != EOF);
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading after write.
|
||||
ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
|
||||
fclose(fp);
|
||||
|
||||
// Write-only. Never reading. Always writing.
|
||||
fp = fopen("/dev/zero", "w");
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading initially.
|
||||
ASSERT_TRUE(__fwriting(fp)); // Writing initially.
|
||||
ASSERT_TRUE(fputc('x', fp) != EOF);
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading after write.
|
||||
ASSERT_TRUE(__fwriting(fp)); // Still writing after write.
|
||||
fclose(fp);
|
||||
|
||||
// Read-only. Always reading. Never writing.
|
||||
fp = fopen("/dev/zero", "r");
|
||||
ASSERT_TRUE(__freading(fp)); // Reading initially.
|
||||
ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
|
||||
ASSERT_TRUE(fgetc(fp) == 0);
|
||||
ASSERT_TRUE(__freading(fp)); // Still reading after read.
|
||||
ASSERT_FALSE(__fwriting(fp)); // Still not writing after read.
|
||||
fclose(fp);
|
||||
|
||||
// The three read-write modes.
|
||||
for (auto read_write_mode : {"r+", "w+", "a+"}) {
|
||||
fp = fopen("/dev/zero", read_write_mode);
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading initially.
|
||||
ASSERT_FALSE(__fwriting(fp)); // Not writing initially.
|
||||
ASSERT_TRUE(fgetc(fp) == 0);
|
||||
ASSERT_TRUE(__freading(fp)); // Reading after read.
|
||||
ASSERT_FALSE(__fwriting(fp)); // Not writing after read.
|
||||
ASSERT_TRUE(fputc('x', fp) != EOF);
|
||||
ASSERT_FALSE(__freading(fp)); // Not reading after write.
|
||||
ASSERT_TRUE(__fwriting(fp)); // Writing after write.
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(stdio_ext, __fsetlocking) {
|
||||
|
|
Loading…
Reference in a new issue