Initial QFileInputStream implementation

This commit is contained in:
Dan Paulat 2023-01-01 21:44:03 -06:00
parent 08965aa7f3
commit ad6eb61898
5 changed files with 218 additions and 5 deletions

View file

@ -161,13 +161,15 @@ set(HDR_UTIL source/scwx/qt/util/color.hpp
source/scwx/qt/util/json.hpp
source/scwx/qt/util/streams.hpp
source/scwx/qt/util/texture_atlas.hpp
source/scwx/qt/util/q_file_buffer.hpp)
source/scwx/qt/util/q_file_buffer.hpp
source/scwx/qt/util/q_file_input_stream.hpp)
set(SRC_UTIL source/scwx/qt/util/color.cpp
source/scwx/qt/util/font.cpp
source/scwx/qt/util/font_buffer.cpp
source/scwx/qt/util/json.cpp
source/scwx/qt/util/texture_atlas.cpp
source/scwx/qt/util/q_file_buffer.cpp)
source/scwx/qt/util/q_file_buffer.cpp
source/scwx/qt/util/q_file_input_stream.cpp)
set(HDR_VIEW source/scwx/qt/view/level2_product_view.hpp
source/scwx/qt/view/level3_product_view.hpp
source/scwx/qt/view/level3_radial_view.hpp

View file

@ -72,6 +72,13 @@ QFileBuffer::~QFileBuffer() = default;
QFileBuffer::QFileBuffer(QFileBuffer&&) noexcept = default;
QFileBuffer& QFileBuffer::operator=(QFileBuffer&&) noexcept = default;
void QFileBuffer::swap(QFileBuffer& other)
{
// Swap the base class and managed implementation pointer
std::streambuf::swap(other);
p.swap(other.p);
}
bool QFileBuffer::is_open() const
{
return p->file_.isOpen();
@ -147,7 +154,7 @@ QFileBuffer::int_type QFileBuffer::pbackfail(int_type c)
traits_type::eq_int_type(traits_type::to_int_type(gptr()[-1]), c)))
{
// Just back up position
gbump(static_cast<int>(sizeof(char_type)) * -1);
gbump(-1);
return traits_type::not_eof(c);
}
else if (!is_open() || traits_type::eq_int_type(traits_type::eof(), c))
@ -274,7 +281,7 @@ QFileBuffer::int_type QFileBuffer::uflow()
{
// Return buffered
int_type c = traits_type::to_int_type(*gptr());
gbump(sizeof(char_type));
gbump(1);
return c;
}

View file

@ -29,7 +29,7 @@ public:
explicit QFileBuffer();
/**
* Constructs a new QFileBuffer object, then associated the object with a
* Constructs a new QFileBuffer object, then associates the object with a
* file by calling open(filename, mode). If the open call is successful,
* is_open() returns true.
*/
@ -43,6 +43,13 @@ public:
QFileBuffer(QFileBuffer&&) noexcept;
QFileBuffer& operator=(QFileBuffer&&) noexcept;
/**
* @brief Swaps two QFileBuffer objects
*
* Exchanges the contents of the QFile buffer with those of the other.
*/
void swap(QFileBuffer& other);
/**
* @brief Checks if the associated file is open
*

View file

@ -0,0 +1,96 @@
#include <scwx/qt/util/q_file_input_stream.hpp>
#include <scwx/qt/util/q_file_buffer.hpp>
namespace scwx
{
namespace qt
{
namespace util
{
static const std::string logPrefix_ = "scwx::qt::util::q_file_input_stream";
// Adapted from Microsoft ifstream reference implementation
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
class QFileInputStream::Impl
{
public:
explicit Impl() : buffer_ {} {};
explicit Impl(const std::string& filename, std::ios_base::openmode mode) :
buffer_ {filename, mode} {};
~Impl() = default;
QFileBuffer buffer_;
};
QFileInputStream::QFileInputStream() :
std::istream(nullptr), p(std::make_unique<Impl>())
{
std::basic_ios<char_type, traits_type>::rdbuf(&p->buffer_);
}
QFileInputStream::QFileInputStream(const std::string& filename,
std::ios_base::openmode mode) :
std::istream(nullptr),
p(std::make_unique<Impl>(filename, mode | std::ios_base::in))
{
std::basic_ios<char_type, traits_type>::rdbuf(&p->buffer_);
if (!p->buffer_.is_open())
{
setstate(std::ios_base::failbit);
}
}
QFileInputStream::~QFileInputStream() = default;
QFileInputStream::QFileInputStream(QFileInputStream&& other) noexcept :
std::istream(nullptr), p(std::make_unique<Impl>())
{
swap(other);
};
QFileInputStream&
QFileInputStream::operator=(QFileInputStream&&) noexcept = default;
void QFileInputStream::swap(QFileInputStream& other)
{
// Swap the base class and managed implementation pointer
std::istream::swap(other);
p.swap(other.p);
}
bool QFileInputStream::is_open() const
{
return p->buffer_.is_open();
}
void QFileInputStream::open(const std::string& filename,
std::ios_base::openmode mode)
{
if (p->buffer_.open(filename, mode | std::ios_base::in) == nullptr)
{
setstate(std::ios_base::failbit);
}
else
{
clear();
}
}
void QFileInputStream::close()
{
if (p->buffer_.close() == nullptr)
{
setstate(std::ios_base::failbit);
}
}
QFileBuffer* QFileInputStream::rdbuf() const
{
return &p->buffer_;
}
} // namespace util
} // namespace qt
} // namespace scwx

View file

@ -0,0 +1,101 @@
#pragma once
#include <istream>
namespace scwx
{
namespace qt
{
namespace util
{
class QFileBuffer;
/**
* The QFileInputStream class is a std::istream interface to a QFile, allowing
* use with C++ stream-based I/O.
*
* Documentation for functions derived from
* https://en.cppreference.com/ SPDX-License-Identifier: CC BY-SA 3.0
*/
class QFileInputStream : public std::istream
{
public:
/**
* Constructs a new QFileInputStream object. The created object is not
* associated with a file: default-constructs the QFileBuffer and constructs
* the base with the pointer to this default-constructed QFileBuffer member.
*/
explicit QFileInputStream();
/**
* Constructs a new QFileInputStream object, then associates the object with
* a file by calling rdbuf()->open(filename, mode | std::ios_base::in). If
* the open() call returns a null pointer, sets setstate(failbit).
*/
explicit QFileInputStream(const std::string& filename,
std::ios_base::openmode mode = std::ios_base::in);
~QFileInputStream();
QFileInputStream(const QFileInputStream&) = delete;
QFileInputStream& operator=(const QFileInputStream&) = delete;
QFileInputStream(QFileInputStream&&) noexcept;
QFileInputStream& operator=(QFileInputStream&&) noexcept;
/**
* @brief Swaps two QFileInputStream objects
*
* Exchanges the contents of the QFile input stream with those of the other.
*/
void swap(QFileInputStream& other);
/**
* @brief Checks if the stream has an associated file
*
* Checks if the file stream has an associated file. Effectively calls
* rdbuf()->is_open().
*
* @return true if the associated file is open, false otherwise
*/
bool is_open() const;
/**
* @brief Opens a file and associates it with the stream
*
* Opens and associates the file with name filename with the file stream.
* Effectively calls rdbuf()->open(filename, mode | ios_base::in). Calls
* setstate(failbit) on failure.
*
* @param filename The file name to open
* @param openmode The file opening mode, a binary OR of the std::ios_base
* modes
*/
void open(const std::string& filename,
std::ios_base::openmode mode = std::ios_base::in);
/**
* @brief Close the associated file
*
* Closes the associated file. Effectively calls rdbuf()->close(). If an
* error occurs during operation, setstate(failbit) is called.
*/
void close();
/**
* @brief Returns the underlying raw file device object
*
* Returns a pointer to the underlying raw file device object.
*
* @return Pointer to the underlying raw file device
*/
QFileBuffer* rdbuf() const;
private:
class Impl;
std::unique_ptr<Impl> p;
};
} // namespace util
} // namespace qt
} // namespace scwx