File: file.hpp

package info (click to toggle)
dnf5 5.4.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 17,960 kB
  • sloc: cpp: 94,312; python: 3,370; xml: 1,073; ruby: 600; sql: 250; ansic: 232; sh: 104; perl: 62; makefile: 30
file content (184 lines) | stat: -rw-r--r-- 7,377 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// Copyright Contributors to the DNF5 project.
// Copyright Contributors to the libdnf project.
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// This file is part of libdnf: https://github.com/rpm-software-management/libdnf/
//
// Libdnf is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Libdnf is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with libdnf.  If not, see <https://www.gnu.org/licenses/>.

#ifndef LIBDNF5_UTILS_FS_FILE_HPP
#define LIBDNF5_UTILS_FS_FILE_HPP

#include "libdnf5/defs.h"

#include <cstdio>
#include <filesystem>


namespace libdnf5::utils::fs {

/// A wrapper for a `FILE *` that handles opening and closing a file in RAII
/// fashion. Errors are handled by raising instances of
/// `libdnf5::FileSystemError` so that there's a single exception type
/// being raised for all filesystem-related errors.
class LIBDNF_API File {
public:
    /// Creates an instance of `File` without opening any file.
    File();

    /// Creates an instance of `File` and opens the file at `path` using mode `mode`.
    ///
    /// @param path The path of the file.
    /// @param mode The mode for opening the file.
    /// @param use_solv_xfopen Use libsolv's solv_xfopen to transparently work
    ///                        with compressed files (based on filename
    ///                        extension).
    File(const std::filesystem::path & path, const char * mode, bool use_solv_xfopen = false);

    /// Creates an instance of `File` by opening file descriptor `fd`. The
    /// `path` argument is only used for error reporting and for retrieving from
    /// the object via `get_path()`.
    ///
    /// @param fd The file descriptor to call fdopen() on.
    /// @param path The path of the file, for error reporting etc.
    /// @param mode The mode for opening the file.
    /// @param use_solv_xfopen_fd Use libsolv's solv_xfopen_fd to transparently
    ///                           work with compressed files (based on filename
    ///                           extension).
    File(int fd, const std::filesystem::path & path, const char * mode, bool use_solv_xfopen_fd = false);

    File(const File &) = delete;
    File & operator=(const File &) = delete;
    File(File && f) noexcept;
    File & operator=(File && f);
    ~File();

    /// Opens the file at `path` using mode `mode`. If this object already has
    /// an open file, closes it first before opening the new one.
    ///
    /// @param path The path of the file.
    /// @param mode The mode for opening the file.
    /// @param use_solv_xfopen Use libsolv's solv_xfopen to transparently work
    ///                        with compressed files (based on filename
    ///                        extension).
    void open(const std::filesystem::path & path, const char * mode, bool use_solv_xfopen = false);

    /// Opens the file by opening file descriptor `fd` (via `fdopen()`). The
    /// `path` argument is only used for error reporting and for retrieving from
    /// the object via `get_path()`.
    ///
    /// @param fd The file descriptor to call `fdopen()` on.
    /// @param path The path of the file, for error reporting etc.
    /// @param mode The mode for opening the file.
    /// @param use_solv_xfopen_fd Use libsolv's solv_xfopen_fd to transparently
    ///                           work with compressed files (based on filename
    ///                           extension).
    void open(int fd, const std::filesystem::path & path, const char * mode, bool use_solv_xfopen_fd = false);

    /// Close the file.
    void close();

    /// Releases the file, meaning it will no longer be closed on destruction.
    std::FILE * release() noexcept;

    /// Reads at most `count` chars into `buffer`. If EOF is reached, returns a
    /// number smaller than `count`.
    ///
    /// @param buffer The data buffer to read into.
    /// @param count The size of `buffer`.
    /// @return The number of chars read.
    std::size_t read(void * buffer, std::size_t count);

    /// Writes `count` chars from `buffer.
    ///
    /// @param buffer The data buffer to write.
    /// @param count The number of chars to write from `buffer`.
    void write(const void * buffer, std::size_t count);

    /// Reads a single char from the file.
    ///
    /// @param c The char variable to read to.
    /// @return `true` if char was read, `false` in case EOF was reached.
    bool getc(char & c);

    /// Writes a single char to the file.
    ///
    /// @param c The char to write.
    void putc(char c);

    /// Flushes the data from the internal FILE stream buffer.
    void flush();

    /// Seeks to `offset` relative to `whence`. The values for `whence` are
    /// `SEEK_SET`, `SEEK_CUR` and `SEEK_END`, directly from the `<cstdio>`
    /// header.
    ///
    /// @param offset The offset to seek to.
    /// @param whence The relative position to seek from.
    void seek(long offset, int whence);

    /// @return The current position indicator value of the FILE stream.
    long tell() const;

    /// Rewinds the FILE stream to the beginning.
    void rewind();

    /// @return Whether the current position indicator is at the end of file (EOF).
    bool is_at_eof() const;

    /// Reads the contents of the file from current position to the end or until `count` chars are read.
    ///
    /// It will try to detect the number of characters in the file until the end. If the detection is successful,
    /// the required memory is allocated at once. Otherwise, the fallback solution reads the file block by block
    /// and reallocates memory.
    ///
    /// @param count The maximum number of characters to read, 0 to read till the end.
    /// @return The contents read from the file.
    std::string read(std::size_t count = 0);

    /// Reads a single line of the file.
    ///
    /// @param line The string variable to read the line into.
    /// @return `true` if line was read, `false` in case EOF was reached.
    bool read_line(std::string & line);

    /// Writes `data` into the file.
    ///
    /// @param data The data to write.
    void write(std::string_view data);

    /// @return Whether this object contains an open file.
    explicit operator bool() const noexcept;

    /// Returns the associated file path.
    /// @return The associated file path.
    const std::filesystem::path & get_path() const noexcept;

    /// Returns the associated open stream or nullptr.
    /// @return The associated open stream or nullptr.
    std::FILE * get() const noexcept;

    /// Returns the associated open file descriptor.
    /// The operation requires an open file. Throws a `libdnf5::FileSystemError` exception if an error occurs.
    /// @return The associated open file descriptor.
    int get_fd() const;

private:
    std::filesystem::path path;
    std::FILE * file = nullptr;
};

}  // namespace libdnf5::utils::fs

#endif  // LIBDNF5_UTILS_FS_FILE_HPP