1 //===-- Implementation of fopencookie -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/stdio/fopencookie.h"
10 #include "hdr/stdio_macros.h"
11 #include "hdr/types/FILE.h"
12 #include "hdr/types/cookie_io_functions_t.h"
13 #include "hdr/types/off_t.h"
14 #include "src/__support/CPP/new.h"
15 #include "src/__support/File/file.h"
17 #include "src/__support/macros/config.h"
18 #include "src/errno/libc_errno.h"
20 namespace LIBC_NAMESPACE_DECL
{
24 class CookieFile
: public LIBC_NAMESPACE::File
{
26 cookie_io_functions_t ops
;
28 static FileIOResult
cookie_write(File
*f
, const void *data
, size_t size
);
29 static FileIOResult
cookie_read(File
*f
, void *data
, size_t size
);
30 static ErrorOr
<off_t
> cookie_seek(File
*f
, off_t offset
, int whence
);
31 static int cookie_close(File
*f
);
34 CookieFile(void *c
, cookie_io_functions_t cops
, uint8_t *buffer
,
35 size_t bufsize
, File::ModeFlags mode
)
36 : File(&cookie_write
, &cookie_read
, &CookieFile::cookie_seek
,
37 &cookie_close
, buffer
, bufsize
, 0 /* default buffering mode */,
38 true /* File owns buffer */, mode
),
39 cookie(c
), ops(cops
) {}
42 FileIOResult
CookieFile::cookie_write(File
*f
, const void *data
, size_t size
) {
43 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
44 if (cookie_file
->ops
.write
== nullptr)
46 return static_cast<size_t>(cookie_file
->ops
.write(
47 cookie_file
->cookie
, reinterpret_cast<const char *>(data
), size
));
50 FileIOResult
CookieFile::cookie_read(File
*f
, void *data
, size_t size
) {
51 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
52 if (cookie_file
->ops
.read
== nullptr)
54 return static_cast<size_t>(cookie_file
->ops
.read(
55 cookie_file
->cookie
, reinterpret_cast<char *>(data
), size
));
58 ErrorOr
<off_t
> CookieFile::cookie_seek(File
*f
, off_t offset
, int whence
) {
59 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
60 if (cookie_file
->ops
.seek
== nullptr) {
63 off64_t offset64
= offset
;
64 int result
= cookie_file
->ops
.seek(cookie_file
->cookie
, &offset64
, whence
);
70 int CookieFile::cookie_close(File
*f
) {
71 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
72 if (cookie_file
->ops
.close
== nullptr)
74 int retval
= cookie_file
->ops
.close(cookie_file
->cookie
);
81 } // anonymous namespace
83 LLVM_LIBC_FUNCTION(::FILE *, fopencookie
,
84 (void *cookie
, const char *mode
,
85 cookie_io_functions_t ops
)) {
89 buffer
= new (ac
) uint8_t[File::DEFAULT_BUFFER_SIZE
];
94 auto *file
= new (ac
) CookieFile(
95 cookie
, ops
, buffer
, File::DEFAULT_BUFFER_SIZE
, File::mode_flags(mode
));
98 return reinterpret_cast<::FILE *>(file
);
101 } // namespace LIBC_NAMESPACE_DECL