forked from OSchip/llvm-project
[libc] Add implementation of getc, getc_unlocked and fgetc_unlocked.
Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D137507
This commit is contained in:
parent
4fa00ce15c
commit
6a6101958a
|
@ -376,6 +376,7 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.stdio.ferror
|
||||
libc.src.stdio.ferror_unlocked
|
||||
libc.src.stdio.fgetc
|
||||
libc.src.stdio.fgetc_unlocked
|
||||
libc.src.stdio.fgets
|
||||
libc.src.stdio.fflush
|
||||
libc.src.stdio.fopen
|
||||
|
@ -390,6 +391,8 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.stdio.fwrite
|
||||
libc.src.stdio.fwrite_unlocked
|
||||
libc.src.stdio.fprintf
|
||||
libc.src.stdio.getc
|
||||
libc.src.stdio.getc_unlocked
|
||||
libc.src.stdio.printf
|
||||
libc.src.stdio.putc
|
||||
libc.src.stdio.putchar
|
||||
|
|
|
@ -137,6 +137,11 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
|||
ArgSpec<SizeTType>,
|
||||
ArgSpec<FILERestrictedPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fgetc_unlocked",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
|
|
|
@ -1011,6 +1011,11 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<VoidType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"getc_unlocked",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
|
|
|
@ -568,6 +568,11 @@ def StdC : StandardSpec<"stdc"> {
|
|||
RetValSpec<LongType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"getc",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"putc",
|
||||
RetValSpec<IntType>,
|
||||
|
|
|
@ -113,6 +113,42 @@ add_entrypoint_object(
|
|||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fgetc_unlocked
|
||||
SRCS
|
||||
fgetc_unlocked.cpp
|
||||
HDRS
|
||||
fgetc_unlocked.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
getc
|
||||
SRCS
|
||||
getc.cpp
|
||||
HDRS
|
||||
getc.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
getc_unlocked
|
||||
SRCS
|
||||
getc_unlocked.cpp
|
||||
HDRS
|
||||
getc_unlocked.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fgets
|
||||
SRCS
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
//===-- Implementation of fgetc_unlocked ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/fgetc_unlocked.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, fgetc_unlocked, (::FILE * stream)) {
|
||||
unsigned char c;
|
||||
size_t r =
|
||||
reinterpret_cast<__llvm_libc::File *>(stream)->read_unlocked(&c, 1);
|
||||
if (r != 1)
|
||||
return EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of fgetc_unlocked -----------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_FGETC_UNLOCKED_H
|
||||
#define LLVM_LIBC_SRC_STDIO_FGETC_UNLOCKED_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int fgetc_unlocked(::FILE *f);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_FGETC_UNLOCKED_H
|
|
@ -0,0 +1,24 @@
|
|||
//===-- Implementation of getc --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/getc.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, getc, (::FILE * stream)) {
|
||||
unsigned char c;
|
||||
size_t r = reinterpret_cast<__llvm_libc::File *>(stream)->read(&c, 1);
|
||||
if (r != 1)
|
||||
return EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of getc ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_GETC_H
|
||||
#define LLVM_LIBC_SRC_STDIO_GETC_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int getc(::FILE *f);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_GETC_H
|
|
@ -0,0 +1,25 @@
|
|||
//===-- Implementation of getc_unlocked ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/getc_unlocked.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, getc_unlocked, (::FILE * stream)) {
|
||||
unsigned char c;
|
||||
size_t r =
|
||||
reinterpret_cast<__llvm_libc::File *>(stream)->read_unlocked(&c, 1);
|
||||
if (r != 1)
|
||||
return EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of getc_unlocked ------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_GETC_UNLOCKED_H
|
||||
#define LLVM_LIBC_SRC_STDIO_GETC_UNLOCKED_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int getc_unlocked(::FILE *f);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_GETC_UNLOCKED_H
|
|
@ -216,6 +216,29 @@ add_libc_unittest(
|
|||
libc.src.stdio.fgetc
|
||||
libc.src.stdio.fopen
|
||||
libc.src.stdio.fwrite
|
||||
libc.src.stdio.getc
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
fgetc_unlocked_test
|
||||
SUITE
|
||||
libc_stdio_unittests
|
||||
SRCS
|
||||
fgetc_unlocked_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.stdio
|
||||
libc.src.stdio.fclose
|
||||
libc.src.stdio.ferror
|
||||
libc.src.stdio.ferror_unlocked
|
||||
libc.src.stdio.feof
|
||||
libc.src.stdio.feof_unlocked
|
||||
libc.src.stdio.fgetc_unlocked
|
||||
libc.src.stdio.flockfile
|
||||
libc.src.stdio.fopen
|
||||
libc.src.stdio.funlockfile
|
||||
libc.src.stdio.fwrite
|
||||
libc.src.stdio.getc_unlocked
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
|
|
|
@ -13,38 +13,50 @@
|
|||
#include "src/stdio/fgetc.h"
|
||||
#include "src/stdio/fopen.h"
|
||||
#include "src/stdio/fwrite.h"
|
||||
#include "src/stdio/getc.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
TEST(LlvmLibcFGetCTest, WriteAndReadCharacters) {
|
||||
constexpr char FILENAME[] = "testdata/fgetc.test";
|
||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
constexpr char CONTENT[] = "123456789";
|
||||
constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
|
||||
ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
|
||||
// This is a write-only file so reads should fail.
|
||||
ASSERT_EQ(__llvm_libc::fgetc(file), EOF);
|
||||
// This is an error and not a real EOF.
|
||||
ASSERT_EQ(__llvm_libc::feof(file), 0);
|
||||
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||
errno = 0;
|
||||
class LlvmLibcGetcTest : public __llvm_libc::testing::Test {
|
||||
public:
|
||||
using GetcFunc = int(FILE *);
|
||||
void test_with_func(GetcFunc *func, const char *filename) {
|
||||
::FILE *file = __llvm_libc::fopen(filename, "w");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
constexpr char CONTENT[] = "123456789";
|
||||
constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
|
||||
ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
|
||||
// This is a write-only file so reads should fail.
|
||||
ASSERT_EQ(func(file), EOF);
|
||||
// This is an error and not a real EOF.
|
||||
ASSERT_EQ(__llvm_libc::feof(file), 0);
|
||||
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||
errno = 0;
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
|
||||
file = __llvm_libc::fopen(FILENAME, "r");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
file = __llvm_libc::fopen(filename, "r");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
|
||||
for (size_t i = 0; i < WRITE_SIZE; ++i) {
|
||||
int c = __llvm_libc::fgetc(file);
|
||||
ASSERT_EQ(c, int('1' + i));
|
||||
for (size_t i = 0; i < WRITE_SIZE; ++i) {
|
||||
int c = func(file);
|
||||
ASSERT_EQ(c, int('1' + i));
|
||||
}
|
||||
// Reading more should return EOF but not set error.
|
||||
ASSERT_EQ(func(file), EOF);
|
||||
ASSERT_NE(__llvm_libc::feof(file), 0);
|
||||
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
}
|
||||
// Reading more should return EOF but not set error.
|
||||
ASSERT_EQ(__llvm_libc::fgetc(file), EOF);
|
||||
ASSERT_NE(__llvm_libc::feof(file), 0);
|
||||
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||
};
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetc) {
|
||||
test_with_func(&__llvm_libc::fgetc, "testdata/fgetc.test");
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetc) {
|
||||
test_with_func(&__llvm_libc::getc, "testdata/getc.test");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
//===-- Unittests for fgetc -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/fclose.h"
|
||||
#include "src/stdio/feof.h"
|
||||
#include "src/stdio/feof_unlocked.h"
|
||||
#include "src/stdio/ferror.h"
|
||||
#include "src/stdio/ferror_unlocked.h"
|
||||
#include "src/stdio/fgetc_unlocked.h"
|
||||
#include "src/stdio/flockfile.h"
|
||||
#include "src/stdio/fopen.h"
|
||||
#include "src/stdio/funlockfile.h"
|
||||
#include "src/stdio/fwrite.h"
|
||||
#include "src/stdio/getc_unlocked.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class LlvmLibcGetcTest : public __llvm_libc::testing::Test {
|
||||
public:
|
||||
using GetcFunc = int(FILE *);
|
||||
void test_with_func(GetcFunc *func, const char *filename) {
|
||||
::FILE *file = __llvm_libc::fopen(filename, "w");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
constexpr char CONTENT[] = "123456789";
|
||||
constexpr size_t WRITE_SIZE = sizeof(CONTENT) - 1;
|
||||
ASSERT_EQ(WRITE_SIZE, __llvm_libc::fwrite(CONTENT, 1, WRITE_SIZE, file));
|
||||
// This is a write-only file so reads should fail.
|
||||
ASSERT_EQ(func(file), EOF);
|
||||
// This is an error and not a real EOF.
|
||||
ASSERT_EQ(__llvm_libc::feof(file), 0);
|
||||
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||
errno = 0;
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
|
||||
file = __llvm_libc::fopen(filename, "r");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
|
||||
__llvm_libc::flockfile(file);
|
||||
for (size_t i = 0; i < WRITE_SIZE; ++i) {
|
||||
int c = func(file);
|
||||
ASSERT_EQ(c, int('1' + i));
|
||||
}
|
||||
// Reading more should return EOF but not set error.
|
||||
ASSERT_EQ(func(file), EOF);
|
||||
ASSERT_NE(__llvm_libc::feof_unlocked(file), 0);
|
||||
ASSERT_EQ(__llvm_libc::ferror_unlocked(file), 0);
|
||||
|
||||
__llvm_libc::funlockfile(file);
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithFgetcUnlocked) {
|
||||
test_with_func(&__llvm_libc::fgetc_unlocked, "testdata/fgetc_unlocked.test");
|
||||
}
|
||||
|
||||
TEST_F(LlvmLibcGetcTest, WriteAndReadCharactersWithGetcUnlocked) {
|
||||
test_with_func(&__llvm_libc::getc_unlocked, "testdata/getc_unlocked.test");
|
||||
}
|
Loading…
Reference in New Issue