use std::filesystem::path instead of std::string

This commit is contained in:
Jinhao 2019-03-07 01:10:02 +08:00
parent 051525fc6f
commit 0a3fb34e09
7 changed files with 111 additions and 121 deletions

View File

@ -428,7 +428,7 @@ namespace nana { namespace experimental { namespace filesystem
file_status status(const path& p, std::error_code&);
std::uintmax_t file_size(const path& p);
//uintmax_t file_size(const path& p, error_code& ec) noexcept;
std::uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
inline bool is_directory(file_status s) noexcept
{ return s.type() == file_type::directory ;}

View File

@ -1,7 +1,7 @@
/*
* A text editor implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -66,6 +66,7 @@ namespace nana{ namespace widgets
using char_type = wchar_t;
using size_type = textbase<char_type>::size_type;
using string_type = textbase<char_type>::string_type;
using path_type = std::filesystem::path;
using event_interface = text_editor_event_interface;
@ -105,7 +106,7 @@ namespace nana{ namespace widgets
void indent(bool, std::function<std::string()> generator);
void set_event(event_interface*);
bool load(const char*);
bool load(const path_type& file);
void text_align(::nana::align alignment);

View File

@ -1,7 +1,7 @@
/*
* A textbase class implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -18,10 +18,11 @@
#include <nana/charset.hpp>
#include <nana/basic_types.hpp>
#include <nana/traits.hpp>
#include <nana/filesystem/filesystem.hpp>
#include "textbase_export_interface.hpp"
#include <deque>
#include <memory>
#include <fstream>
#include <stdexcept>
@ -36,15 +37,16 @@ namespace skeletons
: public ::nana::noncopyable
{
public:
typedef CharT char_type;
typedef std::basic_string<CharT> string_type;
typedef typename string_type::size_type size_type;
using char_type = CharT;
using string_type = std::basic_string<CharT>;
using size_type = typename string_type::size_type;
using path_type = std::filesystem::path;
textbase()
{
attr_max_.reset();
//Insert an empty string for the first line of empty text.
text_cont_.emplace_back(new string_type);
text_cont_.emplace_back();
}
void set_event_agent(textbase_event_agent_interface * evt)
@ -55,21 +57,19 @@ namespace skeletons
bool empty() const
{
return (text_cont_.empty() ||
((text_cont_.size() == 1) && (text_cont_.front()->empty())));
((text_cont_.size() == 1) && text_cont_.front().empty()));
}
bool load(const char* file_utf8)
bool load(const path_type& file)
{
if (!file_utf8)
return false;
std::ifstream ifs(to_osmbstr(file_utf8));
std::ifstream ifs{ file.string() };
if (!ifs)
return false;
ifs.seekg(0, std::ios::end);
std::size_t bytes = static_cast<std::size_t>(ifs.tellg());
ifs.seekg(0, std::ios::beg);
std::error_code err;
auto const bytes = file_size(file, err);
if (err)
return false;
if(bytes >= 2)
{
@ -81,7 +81,7 @@ namespace skeletons
if(0xBB == ch && 0xBF == ifs.get())
{
ifs.close();
return load(file_utf8, nana::unicode::utf8);
return load(file, nana::unicode::utf8);
}
}
else if(0xFF == ch)
@ -89,16 +89,13 @@ namespace skeletons
if(0xFE == ifs.get())
{
//UTF16,UTF32
if(bytes >= 4)
if((bytes >= 4) && (ifs.get() == 0 && ifs.get() == 0))
{
if(ifs.get() == 0 && ifs.get() == 0)
{
ifs.close();
return load(file_utf8, nana::unicode::utf32);
}
ifs.close();
return load(file, nana::unicode::utf32);
}
ifs.close();
return load(file_utf8, nana::unicode::utf16);
return load(file, nana::unicode::utf16);
}
}
else if(0xFE == ch)
@ -107,7 +104,7 @@ namespace skeletons
{
//UTF16(big-endian)
ifs.close();
return load(file_utf8, nana::unicode::utf16);
return load(file, nana::unicode::utf16);
}
}
else if(0 == ch)
@ -119,7 +116,7 @@ namespace skeletons
{
//UTF32(big_endian)
ifs.close();
return load(file_utf8, nana::unicode::utf32);
return load(file, nana::unicode::utf32);
}
}
}
@ -135,15 +132,15 @@ namespace skeletons
while(ifs.good())
{
std::getline(ifs, str_mbs);
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str_mbs })));
if(text_cont_.back()->size() > attr_max_.size)
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str_mbs }));
if (text_cont_.back().size() > attr_max_.size)
{
attr_max_.size = text_cont_.back()->size();
attr_max_.size = text_cont_.back().size();
attr_max_.line = text_cont_.size() - 1;
}
}
_m_saved(file_utf8);
_m_saved(file);
return true;
}
@ -175,12 +172,9 @@ namespace skeletons
}
}
bool load(const char* file_utf8, nana::unicode encoding)
bool load(const path_type& file, nana::unicode encoding)
{
if (!file_utf8)
return false;
std::ifstream ifs(to_osmbstr(file_utf8));
std::ifstream ifs{ file.string() };
if (!ifs)
return false;
@ -218,9 +212,8 @@ namespace skeletons
byte_order_translate_4bytes(str);
}
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
attr_max_.size = text_cont_.back()->size();
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
attr_max_.size = text_cont_.back().size();
attr_max_.line = 0;
}
@ -236,21 +229,21 @@ namespace skeletons
byte_order_translate_4bytes(str);
}
text_cont_.emplace_back(new string_type(static_cast<string_type&&>(nana::charset{ str, encoding })));
if(text_cont_.back()->size() > attr_max_.size)
text_cont_.emplace_back(static_cast<string_type&&>(nana::charset{ str, encoding }));
if (text_cont_.back().size() > attr_max_.size)
{
attr_max_.size = text_cont_.back()->size();
attr_max_.size = text_cont_.back().size();
attr_max_.line = text_cont_.size() - 1;
}
}
_m_saved(file_utf8);
_m_saved(file);
return true;
}
void store(std::string fs, bool is_unicode, ::nana::unicode encoding) const
void store(const path_type& filename, bool is_unicode, ::nana::unicode encoding) const
{
std::ofstream ofs(to_osmbstr(fs), std::ios::binary);
std::ofstream ofs(filename.string(), std::ios::binary);
if(ofs && text_cont_.size())
{
auto i = text_cont_.cbegin();
@ -277,27 +270,26 @@ namespace skeletons
for (std::size_t pos = 0; pos < count; ++pos)
{
auto mbs = nana::charset(**(i++)).to_bytes(encoding);
auto mbs = nana::charset(*(i++)).to_bytes(encoding);
ofs.write(mbs.c_str(), static_cast<std::streamsize>(mbs.size()));
ofs.write("\r\n", 2);
}
last_mbs = nana::charset(*text_cont_.back()).to_bytes(encoding);
last_mbs = nana::charset(text_cont_.back()).to_bytes(encoding);
}
else
{
for (std::size_t pos = 0; pos < count; ++pos)
{
std::string mbs = nana::charset(**(i++));
std::string mbs = nana::charset(*(i++));
ofs.write(mbs.c_str(), mbs.size());
ofs.write("\r\n", 2);
}
last_mbs = nana::charset(*text_cont_.back());
last_mbs = nana::charset(text_cont_.back());
}
ofs.write(last_mbs.c_str(), static_cast<std::streamsize>(last_mbs.size()));
_m_saved(std::move(fs));
_m_saved(filename);
}
}
@ -311,7 +303,7 @@ namespace skeletons
{
if (!changed_)
{
_m_first_change();
_m_emit_first_change();
changed_ = true;
}
@ -332,8 +324,7 @@ namespace skeletons
const string_type& getline(size_type pos) const
{
if (pos < text_cont_.size())
return *text_cont_[pos];
return text_cont_[pos];
return nullstr_;
}
@ -346,7 +337,7 @@ namespace skeletons
{
if (text_cont_.size() <= pos)
{
text_cont_.emplace_back(new string_type(std::move(text)));
text_cont_.emplace_back(std::move(text));
pos = text_cont_.size() - 1;
}
else
@ -369,7 +360,7 @@ namespace skeletons
}
else
{
text_cont_.emplace_back(new string_type(std::move(str)));
text_cont_.emplace_back(std::move(str));
pos.y = static_cast<unsigned>(text_cont_.size() - 1);
}
@ -380,9 +371,9 @@ namespace skeletons
void insertln(size_type pos, string_type&& str)
{
if (pos < text_cont_.size())
text_cont_.emplace(_m_iat(pos), new string_type(std::move(str)));
text_cont_.emplace(_m_iat(pos), std::move(str));
else
text_cont_.emplace_back(new string_type(std::move(str)));
text_cont_.emplace_back(std::move(str));
_m_make_max(pos);
edited_ = true;
@ -429,9 +420,9 @@ namespace skeletons
{
text_cont_.clear();
attr_max_.reset();
text_cont_.emplace_back(new string_type); //text_cont_ must not be empty
text_cont_.emplace_back(); //text_cont_ must not be empty
_m_saved(std::string());
_m_saved({});
}
void merge(size_type pos)
@ -439,7 +430,8 @@ namespace skeletons
if(pos + 1 < text_cont_.size())
{
auto i = _m_iat(pos + 1);
_m_at(pos) += **i;
_m_at(pos) += *i;
text_cont_.erase(i);
_m_make_max(pos);
@ -453,7 +445,7 @@ namespace skeletons
}
}
const std::string& filename() const
const path_type& filename() const
{
return filename_;
}
@ -463,33 +455,25 @@ namespace skeletons
return changed_;
}
void edited_reset()
void reset_status(bool remain_saved_filename)
{
changed_ = false;
}
if(!remain_saved_filename)
filename_.clear();
void reset()
{
filename_.clear();
changed_ = false;
}
bool saved() const
{
return ! not_saved();
}
bool not_saved() const
{
return edited() || filename_.empty();
return !(changed_ || filename_.empty());
}
private:
string_type& _m_at(size_type pos)
{
return **_m_iat(pos);
return *_m_iat(pos);
}
typename std::deque<std::unique_ptr<string_type>>::iterator _m_iat(size_type pos)
typename std::deque<string_type>::iterator _m_iat(size_type pos)
{
return text_cont_.begin() + pos;
}
@ -506,50 +490,40 @@ namespace skeletons
void _m_scan_for_max()
{
attr_max_.size = 0;
std::size_t n = 0;
for(auto & p : text_cont_)
{
if(p->size() > attr_max_.size)
{
attr_max_.size = p->size();
attr_max_.line = n;
}
++n;
}
attr_max_.reset();
for (std::size_t i = 0; i < text_cont_.size(); ++i)
_m_make_max(i);
}
void _m_first_change() const
void _m_emit_first_change() const
{
if (evt_agent_)
evt_agent_->first_change();
}
void _m_saved(std::string && filename) const
void _m_saved(const path_type& filename) const
{
if(filename_ != filename)
if((filename_ != filename) || changed_)
{
filename_ = std::move(filename);
_m_first_change();
filename_ = filename;
_m_emit_first_change();
}
else if(changed_)
_m_first_change();
changed_ = false;
}
private:
std::deque<std::unique_ptr<string_type>> text_cont_;
std::deque<string_type> text_cont_;
textbase_event_agent_interface* evt_agent_{ nullptr };
mutable bool changed_{ false };
mutable bool edited_{ false };
mutable std::string filename_; //A string for the saved filename.
mutable path_type filename_; ///< The saved filename
const string_type nullstr_;
struct attr_max
{
std::size_t line;
std::size_t size;
std::size_t line; ///< The line number of max line
std::size_t size; ///< The number of characters in max line
void reset()
{

View File

@ -1,7 +1,7 @@
/**
* A Textbox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -109,6 +109,8 @@ namespace nana
using text_focus_behavior = widgets::skeletons::text_focus_behavior;
using text_positions = std::vector<upoint>;
using path_type = std::filesystem::path;
/// The default constructor without creating the widget.
textbox();
@ -136,9 +138,9 @@ namespace nana
textbox(window, const rectangle& = rectangle(), bool visible = true);
/// \brief Loads a text file. When attempt to load a unicode encoded text file, be sure the file have a BOM header.
void load(std::string file);
void store(std::string file);
void store(std::string file, nana::unicode encoding);
void load(const path_type& file);
void store(const path_type& file);
void store(const path_type& file, nana::unicode encoding);
colored_area_access_interface* colored_area_access();
@ -158,7 +160,7 @@ namespace nana
textbox& reset(const std::string& text = std::string(), bool end_caret = true); ///< discard the old text and set a new text
/// The file of last store operation.
std::string filename() const;
path_type filename() const;
/// Determine whether the text was edited.
bool edited() const;

View File

@ -936,7 +936,7 @@ namespace nana { namespace experimental { namespace filesystem
auto stat = status(p, err);
if (err != std::error_code())
throw filesystem_error("nana::experimental::filesystem::status", p, err);
throw filesystem_error("nana::filesystem::status", p, err);
return stat;
}
@ -1002,6 +1002,16 @@ namespace nana { namespace experimental { namespace filesystem
std::uintmax_t file_size(const path& p)
{
std::error_code err;
auto bytes = file_size(p, err);
if (err)
throw filesystem_error("nana::filesystem::status", p, err);
return bytes;
}
std::uintmax_t file_size(const path& p, std::error_code& ec)
{
#if defined(NANA_WINDOWS)
//Some compilation environment may fail to link to GetFileSizeEx
typedef BOOL(__stdcall *GetFileSizeEx_fptr_t)(HANDLE, PLARGE_INTEGER);
@ -1019,23 +1029,25 @@ namespace nana { namespace experimental { namespace filesystem
return li.QuadPart;
}
}
return 0;
ec.assign(static_cast<int>(::GetLastError()), std::generic_category());
#elif defined(NANA_POSIX)
FILE * stream = ::fopen(p.c_str(), "rb");
long long size = 0;
if (stream)
{
long long bytes = 0;
# if defined(NANA_LINUX)
fseeko64(stream, 0, SEEK_END);
size = ftello64(stream);
bytes = ftello64(stream);
# elif defined(NANA_POSIX)
fseeko(stream, 0, SEEK_END);
size = ftello(stream);
bytes = ftello(stream);
# endif
::fclose(stream);
return bytes;
}
return size;
ec.assign(static_cast<int>(::errno), std::generic_category());
#endif
return static_cast<std::uintmax_t>(-1);
}

View File

@ -1275,7 +1275,7 @@ namespace nana {
event_handler_ = ptr;
}
bool text_editor::load(const char* fs)
bool text_editor::load(const path_type& fs)
{
if (!impl_->textbase.load(fs))
return false;

View File

@ -1,7 +1,7 @@
/*
* A Textbox Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2019 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -233,31 +233,31 @@ namespace drawerbase {
create(wd, r, visible);
}
void textbox::load(std::string file)
void textbox::load(const std::filesystem::path& file)
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor && editor->load(file.data()))
if (editor && editor->load(file))
{
if (editor->try_refresh())
API::update_window(handle());
}
}
void textbox::store(std::string file)
void textbox::store(const std::filesystem::path& file)
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
editor->textbase().store(std::move(file), false, nana::unicode::utf8); //3rd parameter is just for syntax, it will be ignored
editor->textbase().store(file, false, nana::unicode::utf8); //3rd parameter is just for syntax, it will be ignored
}
void textbox::store(std::string file, nana::unicode encoding)
void textbox::store(const std::filesystem::path& file, nana::unicode encoding)
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
editor->textbase().store(std::move(file), true, encoding);
editor->textbase().store(file, true, encoding);
}
textbox::colored_area_access_interface* textbox::colored_area_access()
@ -300,7 +300,8 @@ namespace drawerbase {
if (end_caret)
editor->move_caret_end(true);
editor->textbase().reset();
//Reset the edited status and the saved filename
editor->textbase().reset_status(false);
if (editor->try_refresh())
API::update_window(this->handle());
@ -308,7 +309,7 @@ namespace drawerbase {
return *this;
}
std::string textbox::filename() const
textbox::path_type textbox::filename() const
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
@ -330,7 +331,7 @@ namespace drawerbase {
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
editor->textbase().edited_reset();
editor->textbase().reset_status(true);
return *this;
}