コンテンツにスキップ

TextFileWriter

  • BinaryFileWriter を活用して、テキストファイルを書き出すクラスを実装する。
TextFileWriter.hpp
#pragma once
#include <memory> // std::shared_ptr
#include <string_view> // std::string_view
#include <format> // std::format
#include "Common.hpp"

namespace seccamp
{
	/// @brief テキストファイルを書き出すクラス
	class TextFileWriter
	{
	public:

		/// @brief デフォルトコンストラクタ
		[[nodiscard]]
		TextFileWriter();

		/// @brief ファイルを作成してオープンします。
		/// @param path ファイルパス
		[[nodiscard]]
		explicit TextFileWriter(std::string_view path);

		/// @brief ファイルがオープンされているかを返します。
		/// @return オープンされている場合 true, それ以外の場合は false
		[[nodiscard]]
		bool isOpen() const noexcept;

		/// @brief ファイルがオープンされているかを返します。
		/// @return オープンされている場合 true, それ以外の場合は false
		[[nodiscard]]
		explicit operator bool() const noexcept;

		/// @brief ファイルをオープンします。すでにオープンされている場合はクローズしてから再オープンします。
		/// @param path ファイルパス
		/// @return オープンに成功した場合 true, それ以外の場合は false
		bool open(std::string_view path);

		/// @brief ファイルをクローズします。
		void close();

		/// @brief ファイルに文字列を書き込みます。
		/// @param s 書き込む文字列
		void write(std::string_view s);

		/// @brief ファイルに文字列を書き込み、CRLF(\r\n)を追加します。
		/// @param s 書き込む文字列
		void writeln(std::string_view s);

		/// @brief ファイルに文字列を書き込みます。
		/// @tparam Types 書き込むデータの型
		/// @param fmt 書式文字列
		/// @param args 書き込むデータ
		template <class... Types>
		void write(std::format_string<Types...> fmt, Types&&... args)
		{
			write(std::format(fmt, std::forward<Types>(args)...));
		}

		/// @brief ファイルに文字列を書き込み、CRLF(\r\n)を追加します。
		/// @tparam Types 書き込むデータの型
		/// @param fmt 書式文字列
		/// @param args 書き込むデータ
		template <class... Types>
		void writeln(std::format_string<Types...> fmt, Types&&... args)
		{
			writeln(std::format(fmt, std::forward<Types>(args)...));
		}

		/// @brief ファイルの絶対パスを返します。
		/// @return ファイルの絶対パス。ファイルがオープンされていない場合は空文字列
		[[nodiscard]]
		const std::string& fullPath() const noexcept;

	private:

		class Impl;

		std::shared_ptr<Impl> m_pImpl;
	};
}
TextFileWriter.cpp
#include "TextFileWriter.hpp"
#include "BinaryFileWriter.hpp"

namespace seccamp
{
	class TextFileWriter::Impl
	{
	public:

		Impl() = default;

		~Impl()
		{
			close();
		}

		[[nodiscard]]
		bool isOpen() const noexcept
		{
			return m_binaryFileWriter.isOpen();
		}

		bool open(const std::string_view path)
		{
			return m_binaryFileWriter.open(path);
		}

		void close()
		{
			m_binaryFileWriter.close();
		}

		void write(const std::string_view s)
		{
			m_binaryFileWriter.write(s.data(), s.size());
		}

		[[nodiscard]]
		const std::string& fullPath() const noexcept
		{
			return m_binaryFileWriter.fullPath();
		}

	private:

		BinaryFileWriter m_binaryFileWriter;
	};

	TextFileWriter::TextFileWriter()
		: m_pImpl{ std::make_shared<Impl>() } {}

	TextFileWriter::TextFileWriter(const std::string_view path)
		: TextFileWriter{} // 移譲コンストラクタ
	{
		m_pImpl->open(path);
	}

	bool TextFileWriter::isOpen() const noexcept
	{
		return m_pImpl->isOpen();
	}

	bool TextFileWriter::open(const std::string_view path)
	{
		return m_pImpl->open(path);
	}

	TextFileWriter::operator bool() const noexcept
	{
		return m_pImpl->isOpen();
	}

	void TextFileWriter::close()
	{
		m_pImpl->close();
	}

	void TextFileWriter::write(const std::string_view s)
	{
		m_pImpl->write(s);
	}

	void TextFileWriter::writeln(const std::string_view s)
	{
		m_pImpl->write(s);

		m_pImpl->write("\r\n");
	}

	const std::string& TextFileWriter::fullPath() const noexcept
	{
		return m_pImpl->fullPath();
	}
}