2023-10-11 21:50:35 +00:00
|
|
|
///
|
|
|
|
/// \file Buffer.h
|
|
|
|
/// \author kyle
|
|
|
|
/// \date 2023-10-10
|
|
|
|
/// \brief A buffer is the basic document type.
|
|
|
|
///
|
|
|
|
|
|
|
|
#ifndef KEPP_FRAME_H
|
|
|
|
#define KEPP_FRAME_H
|
|
|
|
|
|
|
|
|
2023-10-12 02:25:24 +00:00
|
|
|
#include <cstdint>
|
2023-10-11 22:01:48 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2023-10-11 21:50:35 +00:00
|
|
|
#include "Defs.h"
|
|
|
|
#include "File.h"
|
2023-10-12 02:25:24 +00:00
|
|
|
#include "Cursor.h"
|
2023-10-11 21:50:35 +00:00
|
|
|
|
|
|
|
|
2023-10-12 06:27:42 +00:00
|
|
|
typedef std::vector<std::vector<uint8_t>> BufferContents;
|
2023-10-11 21:50:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
/// A Buffer is the atom of text editing. It represents a single document,
|
|
|
|
/// whether a memory-only buffer or a file-backed buffer.
|
|
|
|
///
|
|
|
|
/// \details
|
|
|
|
///
|
|
|
|
/// There are currently two main types of Buffers: file-backed and virtual.
|
|
|
|
/// A virtual buffer describes any buffer that isn't backed by a file.
|
|
|
|
///
|
|
|
|
/// A virtual buffer can be promoted to a file frame, but a file buffer
|
|
|
|
/// cannot be demoted to a virtual buffer.
|
|
|
|
class Buffer {
|
|
|
|
public:
|
2023-10-12 06:27:42 +00:00
|
|
|
enum class FileStatus : uint8_t {
|
|
|
|
/// The file operation succeeded correctly.
|
|
|
|
FileStatusOK = 0,
|
2023-10-12 22:15:09 +00:00
|
|
|
|
|
|
|
/// There was an error, but it wasn't handled correctly.
|
|
|
|
/// This is mostly for debugging purposes, and shouldn't
|
|
|
|
/// be seen by users.
|
|
|
|
///
|
|
|
|
/// \detail This is set at the beginning of failable
|
|
|
|
/// operations, and indicates that the right
|
|
|
|
/// status wasn't set correctly.
|
|
|
|
FileStatusUnspecifiedError = 1,
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
/// The file can't be written to because it is marked
|
|
|
|
/// read-only. This refers to a buffer being marked as
|
|
|
|
/// read-only, not to whether the underlying file is
|
|
|
|
/// actually read-only.
|
2023-10-12 22:15:09 +00:00
|
|
|
FileStatusReadOnly = 2,
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
/// There was an I/O error trying to write to the file.
|
2023-10-12 22:15:09 +00:00
|
|
|
FileStatusIOFailed = 3,
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
/// The Buffer couldn't be flushed because it is a virtual
|
|
|
|
/// buffer. If the user explicitly tried to save the buffer,
|
|
|
|
/// they should be prompted for a path.
|
2023-10-12 22:15:09 +00:00
|
|
|
FileStatusVirtual = 4,
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
/// The underlying file doesn't have the right permissions;
|
|
|
|
/// for example, it's not writeable if the user is trying to
|
|
|
|
/// write the file.
|
2023-10-12 22:15:09 +00:00
|
|
|
FileStatusInvalidPermissions = 5,
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
/// The underlying file doesn't exist.
|
2023-10-12 22:15:09 +00:00
|
|
|
FileStatusNonExistent = 6,
|
|
|
|
|
2023-10-12 06:27:42 +00:00
|
|
|
};
|
|
|
|
|
2023-10-12 07:22:30 +00:00
|
|
|
static std::string FileStatusToString(FileStatus status);
|
|
|
|
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
static bool StatusOK(FileStatus status)
|
|
|
|
{ return status == FileStatus::FileStatusOK; }
|
|
|
|
|
|
|
|
|
2023-10-11 21:50:35 +00:00
|
|
|
/// The constructor with no arguments generates a new anonymous
|
|
|
|
/// buffer.
|
|
|
|
Buffer();
|
|
|
|
|
|
|
|
/// A single constructor generates a virtual buffer.
|
|
|
|
Buffer(std::string fName);
|
|
|
|
|
|
|
|
/// Instantiate a Buffer pointing to fPath.
|
|
|
|
Buffer(std::string fName, std::string fPath);
|
|
|
|
|
2023-10-12 07:22:30 +00:00
|
|
|
void Close();
|
|
|
|
|
|
|
|
/// Instantiate a buffer from a filesystem path.
|
|
|
|
Buffer(std::filesystem::path fPath);
|
|
|
|
|
2023-10-12 06:27:42 +00:00
|
|
|
std::string Name() const
|
|
|
|
{ return this->name; }
|
|
|
|
|
|
|
|
bool IsVirtual()
|
2023-10-12 07:22:30 +00:00
|
|
|
{ return !this->file.has_value(); }
|
2023-10-12 06:27:42 +00:00
|
|
|
|
|
|
|
Buffer::FileStatus Flush(OptString altPath);
|
|
|
|
|
|
|
|
/// Refresh reads the contents of the file back into the
|
|
|
|
/// buffer.
|
|
|
|
///
|
|
|
|
/// \warning This does not care if the file is dirty or not -
|
|
|
|
/// it WILL overwrite the contents of the buffer.
|
|
|
|
///
|
|
|
|
/// \return A FileStatus indicating whether the read was successful.
|
|
|
|
Buffer::FileStatus Refresh();
|
|
|
|
|
|
|
|
void ChangePath(std::string newPath);
|
2023-10-11 21:50:35 +00:00
|
|
|
|
2023-10-12 22:15:09 +00:00
|
|
|
Cursor Where()
|
2023-10-12 06:27:42 +00:00
|
|
|
{ return this->cursor; }
|
2023-10-11 21:50:35 +00:00
|
|
|
|
2023-10-12 06:27:42 +00:00
|
|
|
void MarkDirty();
|
|
|
|
bool IsDirty()
|
|
|
|
{ return this->dirty; }
|
2023-10-11 21:50:35 +00:00
|
|
|
|
2023-10-12 07:22:30 +00:00
|
|
|
size_t Size();
|
|
|
|
|
2023-10-12 22:15:09 +00:00
|
|
|
/// Does this buffer have a current, on-disk file?
|
|
|
|
///
|
|
|
|
/// \return True if this is a file buffer with an extant source
|
|
|
|
/// file.
|
|
|
|
bool Exists();
|
|
|
|
|
|
|
|
/// PrintBufferStatus is a debug tool to capture the current
|
|
|
|
/// buffer state.
|
|
|
|
void PrintBufferStatus(std::ostream &os);
|
2023-10-11 21:50:35 +00:00
|
|
|
private:
|
2023-10-12 06:27:42 +00:00
|
|
|
void clearContents();
|
|
|
|
|
2023-10-12 22:15:09 +00:00
|
|
|
Cursor cursor;
|
|
|
|
bool dirty;
|
|
|
|
std::string name;
|
|
|
|
OptString path;
|
|
|
|
OptFile file;
|
|
|
|
BufferContents contents;
|
|
|
|
FileStatus status;
|
2023-10-11 21:50:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // KEPP_FRAME_H
|
|
|
|
|