diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2022-02-06 15:27:17 +0000 |
---|---|---|
committer | Tim Flynn <trflynn89@pm.me> | 2022-02-16 19:49:41 -0500 |
commit | e548aab387ecf9778fbb4b8393fb18f83b874c55 (patch) | |
tree | 467086044519842682727cd27ce52f5fff5af831 /Userland/Libraries/LibCore | |
parent | cd0ffe5460489744e41f8eceaa07e1dc29a85a06 (diff) | |
download | serenity-e548aab387ecf9778fbb4b8393fb18f83b874c55.zip |
LibCore: Migrate ConfigFile to Core::Stream API :^)
As part of this, moved the call to `reparse()` out of the constructor
and into the factory methods, to allow the error to propagate.
Diffstat (limited to 'Userland/Libraries/LibCore')
-rw-r--r-- | Userland/Libraries/LibCore/ConfigFile.cpp | 69 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/ConfigFile.h | 12 |
2 files changed, 48 insertions, 33 deletions
diff --git a/Userland/Libraries/LibCore/ConfigFile.cpp b/Userland/Libraries/LibCore/ConfigFile.cpp index ec2fb3007b..5e494c8213 100644 --- a/Userland/Libraries/LibCore/ConfigFile.cpp +++ b/Userland/Libraries/LibCore/ConfigFile.cpp @@ -8,7 +8,6 @@ #include <AK/StringBuilder.h> #include <LibCore/ConfigFile.h> -#include <LibCore/File.h> #include <LibCore/StandardPaths.h> #include <pwd.h> @@ -36,27 +35,37 @@ ErrorOr<NonnullRefPtr<ConfigFile>> ConfigFile::open_for_system(String const& app ErrorOr<NonnullRefPtr<ConfigFile>> ConfigFile::open(String const& filename, AllowWriting allow_altering) { - auto file = File::construct(filename); - if (!file->open(allow_altering == AllowWriting::Yes ? OpenMode::ReadWrite : OpenMode::ReadOnly)) { - // Failure to open a read-only file is OK, and behaves as if the file was empty. - if (allow_altering == AllowWriting::Yes) - return Error::from_string_literal("Unable to open config file"); + auto maybe_file = Stream::File::open(filename, allow_altering == AllowWriting::Yes ? Stream::OpenMode::ReadWrite : Stream::OpenMode::Read); + OwnPtr<Stream::BufferedFile> buffered_file; + if (maybe_file.is_error()) { + // If we attempted to open a read-only file that does not exist, we ignore the error, making it appear + // the same as if we had opened an empty file. This behavior is a little weird, but is required by + // user code, which does not check the config file exists before opening. + if (!(allow_altering == AllowWriting::No && maybe_file.error().code() == ENOENT)) + return maybe_file.error(); + } else { + buffered_file = TRY(Stream::BufferedFile::create(maybe_file.release_value())); } - return adopt_nonnull_ref_or_enomem(new (nothrow) ConfigFile(filename, move(file))); + + auto config_file = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ConfigFile(filename, move(buffered_file)))); + TRY(config_file->reparse()); + return config_file; } ErrorOr<NonnullRefPtr<ConfigFile>> ConfigFile::open(String const& filename, int fd) { - auto file = File::construct(filename); - if (!file->open(fd, OpenMode::ReadWrite, File::ShouldCloseFileDescriptor::Yes)) - return Error::from_string_literal("Unable to open config file"); - return adopt_nonnull_ref_or_enomem(new (nothrow) ConfigFile(filename, move(file))); + auto file = TRY(Stream::File::adopt_fd(fd, Stream::OpenMode::ReadWrite)); + auto buffered_file = TRY(Stream::BufferedFile::create(move(file))); + + auto config_file = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) ConfigFile(filename, move(buffered_file)))); + TRY(config_file->reparse()); + return config_file; } -ConfigFile::ConfigFile(String const&, NonnullRefPtr<File> open_file) - : m_file(move(open_file)) +ConfigFile::ConfigFile(String const& filename, OwnPtr<Stream::BufferedFile> open_file) + : m_filename(filename) + , m_file(move(open_file)) { - reparse(); } ConfigFile::~ConfigFile() @@ -64,26 +73,24 @@ ConfigFile::~ConfigFile() MUST(sync()); } -void ConfigFile::reparse() +ErrorOr<void> ConfigFile::reparse() { m_groups.clear(); + if (!m_file) + return {}; HashMap<String, String>* current_group = nullptr; - while (m_file->can_read_line()) { - auto line = m_file->read_line(); - - if (line.is_null()) { - m_groups.clear(); - return; - } + auto buffer = TRY(ByteBuffer::create_uninitialized(4096)); + while (TRY(m_file->can_read_line())) { + auto length = TRY(m_file->read_line(buffer)); + StringView line { buffer.data(), length }; size_t i = 0; while (i < line.length() && (line[i] == ' ' || line[i] == '\t' || line[i] == '\n')) ++i; - // EOL if (i >= line.length()) continue; @@ -122,6 +129,7 @@ void ConfigFile::reparse() } } } + return {}; } String ConfigFile::read_entry(String const& group, String const& key, String const& default_value) const @@ -159,10 +167,12 @@ void ConfigFile::write_num_entry(String const& group, String const& key, int val { write_entry(group, key, String::number(value)); } + void ConfigFile::write_bool_entry(String const& group, String const& key, bool value) { write_entry(group, key, value ? "true" : "false"); } + void ConfigFile::write_color_entry(String const& group, String const& key, Color value) { write_entry(group, key, String::formatted("{},{},{},{}", value.red(), value.green(), value.blue(), value.alpha())); @@ -173,14 +183,17 @@ ErrorOr<void> ConfigFile::sync() if (!m_dirty) return {}; - m_file->truncate(0); - m_file->seek(0); + if (!m_file) + return Error::from_errno(ENOENT); + + TRY(m_file->truncate(0)); + TRY(m_file->seek(0, Stream::SeekMode::SetPosition)); for (auto& it : m_groups) { - m_file->write(String::formatted("[{}]\n", it.key)); + TRY(m_file->write(String::formatted("[{}]\n", it.key).bytes())); for (auto& jt : it.value) - m_file->write(String::formatted("{}={}\n", jt.key, jt.value)); - m_file->write("\n"); + TRY(m_file->write(String::formatted("{}={}\n", jt.key, jt.value).bytes())); + TRY(m_file->write("\n"sv.bytes())); } m_dirty = false; diff --git a/Userland/Libraries/LibCore/ConfigFile.h b/Userland/Libraries/LibCore/ConfigFile.h index 14b149ff39..8e64d97b39 100644 --- a/Userland/Libraries/LibCore/ConfigFile.h +++ b/Userland/Libraries/LibCore/ConfigFile.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2021, Jakob-Niklas See <git@nwex.de> + * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,7 +13,7 @@ #include <AK/RefPtr.h> #include <AK/String.h> #include <AK/Vector.h> -#include <LibCore/File.h> +#include <LibCore/Stream.h> #include <LibGfx/Color.h> namespace Core { @@ -57,14 +58,15 @@ public: void remove_group(String const& group); void remove_entry(String const& group, String const& key); - String filename() const { return m_file->filename(); } + String const& filename() const { return m_filename; } private: - ConfigFile(String const& filename, NonnullRefPtr<File> open_file); + ConfigFile(String const& filename, OwnPtr<Stream::BufferedFile> open_file); - void reparse(); + ErrorOr<void> reparse(); - NonnullRefPtr<File> m_file; + String m_filename; + OwnPtr<Stream::BufferedFile> m_file; HashMap<String, HashMap<String, String>> m_groups; bool m_dirty { false }; }; |