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 "src/__support/CPP/new.h"
11 #include "src/__support/File/file.h"
13 #include "src/errno/libc_errno.h"
17 namespace LIBC_NAMESPACE
{
21 class CookieFile
: public LIBC_NAMESPACE::File
{
23 cookie_io_functions_t ops
;
25 static FileIOResult
cookie_write(File
*f
, const void *data
, size_t size
);
26 static FileIOResult
cookie_read(File
*f
, void *data
, size_t size
);
27 static ErrorOr
<long> cookie_seek(File
*f
, long offset
, int whence
);
28 static int cookie_close(File
*f
);
31 CookieFile(void *c
, cookie_io_functions_t cops
, uint8_t *buffer
,
32 size_t bufsize
, File::ModeFlags mode
)
33 : File(&cookie_write
, &cookie_read
, &CookieFile::cookie_seek
,
34 &cookie_close
, buffer
, bufsize
, 0 /* default buffering mode */,
35 true /* File owns buffer */, mode
),
36 cookie(c
), ops(cops
) {}
39 FileIOResult
CookieFile::cookie_write(File
*f
, const void *data
, size_t size
) {
40 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
41 if (cookie_file
->ops
.write
== nullptr)
43 return cookie_file
->ops
.write(cookie_file
->cookie
,
44 reinterpret_cast<const char *>(data
), size
);
47 FileIOResult
CookieFile::cookie_read(File
*f
, void *data
, size_t size
) {
48 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
49 if (cookie_file
->ops
.read
== nullptr)
51 return cookie_file
->ops
.read(cookie_file
->cookie
,
52 reinterpret_cast<char *>(data
), size
);
55 ErrorOr
<long> CookieFile::cookie_seek(File
*f
, long offset
, int whence
) {
56 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
57 if (cookie_file
->ops
.seek
== nullptr) {
60 off64_t offset64
= offset
;
61 int result
= cookie_file
->ops
.seek(cookie_file
->cookie
, &offset64
, whence
);
68 int CookieFile::cookie_close(File
*f
) {
69 auto cookie_file
= reinterpret_cast<CookieFile
*>(f
);
70 if (cookie_file
->ops
.close
== nullptr)
72 int retval
= cookie_file
->ops
.close(cookie_file
->cookie
);
79 } // anonymous namespace
81 LLVM_LIBC_FUNCTION(::FILE *, fopencookie
,
82 (void *cookie
, const char *mode
,
83 cookie_io_functions_t ops
)) {
87 buffer
= new (ac
) uint8_t[File::DEFAULT_BUFFER_SIZE
];
92 auto *file
= new (ac
) CookieFile(
93 cookie
, ops
, buffer
, File::DEFAULT_BUFFER_SIZE
, File::mode_flags(mode
));
96 return reinterpret_cast<::FILE *>(file
);
99 } // namespace LIBC_NAMESPACE