mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 21:06:59 -04:00
Clean up pointer use:
* Use unique_ptr for Actions instead of manual memory management * Use unique_ptr in KeywordDatabase * Use unique_ptr instead of shared_ptr for file formats * Don't pass shared_ptr to Reader/Writer, use references instead Also * Switch to C++17 so we can use map::try_emplace
This commit is contained in:
+13
-20
@@ -21,29 +21,22 @@ ActionStack::ActionStack()
|
||||
, last_was_add(false)
|
||||
{}
|
||||
|
||||
ActionStack::~ActionStack() {
|
||||
// we own the actions, delete them
|
||||
FOR_EACH(a, undo_actions) delete a;
|
||||
FOR_EACH(a, redo_actions) delete a;
|
||||
}
|
||||
|
||||
void ActionStack::addAction(Action* action, bool allow_merge) {
|
||||
void ActionStack::addAction(unique_ptr<Action> action, bool allow_merge) {
|
||||
if (!action) return; // no action
|
||||
action->perform(false); // TODO: delete action if perform throws
|
||||
tellListeners(*action, false);
|
||||
// clear redo list
|
||||
if (!redo_actions.empty()) allow_merge = false; // don't merge after undo
|
||||
FOR_EACH(a, redo_actions) delete a;
|
||||
redo_actions.clear();
|
||||
// try to merge?
|
||||
if (allow_merge && !undo_actions.empty() &&
|
||||
last_was_add && // never merge with something that was redone once already
|
||||
undo_actions.back() != save_point && // never merge with the save point
|
||||
last_was_add && // never merge with something that was redone once already
|
||||
undo_actions.back().get() != save_point && // never merge with the save point
|
||||
undo_actions.back()->merge(*action) // merged with top undo action
|
||||
) {
|
||||
delete action;
|
||||
// don't add
|
||||
} else {
|
||||
undo_actions.push_back(action);
|
||||
undo_actions.push_back(move(action));
|
||||
}
|
||||
last_was_add = true;
|
||||
}
|
||||
@@ -51,23 +44,23 @@ void ActionStack::addAction(Action* action, bool allow_merge) {
|
||||
void ActionStack::undo() {
|
||||
assert(canUndo());
|
||||
if (!canUndo()) return;
|
||||
Action* action = undo_actions.back();
|
||||
unique_ptr<Action> action = move(undo_actions.back());
|
||||
undo_actions.pop_back();
|
||||
action->perform(true);
|
||||
tellListeners(*action, true);
|
||||
// move to redo stack
|
||||
undo_actions.pop_back();
|
||||
redo_actions.push_back(action);
|
||||
redo_actions.emplace_back(move(action));
|
||||
last_was_add = false;
|
||||
}
|
||||
void ActionStack::redo() {
|
||||
assert(canRedo());
|
||||
if (!canRedo()) return;
|
||||
Action* action = redo_actions.back();
|
||||
unique_ptr<Action> action = move(redo_actions.back());
|
||||
redo_actions.pop_back();
|
||||
action->perform(false);
|
||||
tellListeners(*action, false);
|
||||
// move to undo stack
|
||||
redo_actions.pop_back();
|
||||
undo_actions.push_back(action);
|
||||
undo_actions.emplace_back(move(action));
|
||||
last_was_add = false;
|
||||
}
|
||||
|
||||
@@ -95,13 +88,13 @@ String ActionStack::redoName() const {
|
||||
|
||||
bool ActionStack::atSavePoint() const {
|
||||
return (undo_actions.empty() && save_point == nullptr)
|
||||
|| (undo_actions.back() == save_point);
|
||||
|| (undo_actions.back().get() == save_point);
|
||||
}
|
||||
void ActionStack::setSavePoint() {
|
||||
if (undo_actions.empty()) {
|
||||
save_point = nullptr;
|
||||
} else {
|
||||
save_point = undo_actions.back();
|
||||
save_point = undo_actions.back().get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,14 +64,13 @@ class ActionListener {
|
||||
class ActionStack {
|
||||
public:
|
||||
ActionStack();
|
||||
~ActionStack();
|
||||
|
||||
/// Add an action to the stack, and perform that action.
|
||||
/** Tells all listeners about the action.
|
||||
* The ActionStack takes ownership of the action.
|
||||
* If allow_merge == true then we attempt to merge this action with previous ones
|
||||
*/
|
||||
void addAction(Action* action, bool allow_merge = true);
|
||||
void addAction(unique_ptr<Action> action, bool allow_merge = true);
|
||||
|
||||
/// Undoes the last action that was (re)done
|
||||
/** @pre canUndo() */
|
||||
@@ -107,13 +106,11 @@ class ActionStack {
|
||||
|
||||
private:
|
||||
/// Actions to be undone.
|
||||
/** Owns the action objects! */
|
||||
vector<Action*> undo_actions;
|
||||
vector<unique_ptr<Action>> undo_actions;
|
||||
/// Actions to be redone
|
||||
/** Owns the action objects! */
|
||||
vector<Action*> redo_actions;
|
||||
vector<unique_ptr<Action>> redo_actions;
|
||||
/// Point at which the file was saved, corresponds to the top of the undo stack at that point
|
||||
Action* save_point;
|
||||
const Action* save_point;
|
||||
/// Was the last thing the user did addAction? (as opposed to undo/redo)
|
||||
bool last_was_add;
|
||||
/// Objects that are listening to actions
|
||||
|
||||
@@ -25,7 +25,8 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const
|
||||
item->read_data.init(init_with);
|
||||
} else if (!item->unread_data.empty()) { // not read, read now
|
||||
item->read_data.init(init_with);
|
||||
Reader reader(make_shared<wxStringInputStream>(item->unread_data), nullptr, _("delayed data for ") + name);
|
||||
wxStringInputStream input(item->unread_data);
|
||||
Reader reader(input, nullptr, _("delayed data for ") + name);
|
||||
reader.handle_greedy(item->read_data);
|
||||
item->unread_data.clear();
|
||||
}
|
||||
|
||||
+44
-44
@@ -26,13 +26,10 @@ IMPLEMENT_DYNAMIC_ARG(Package*, writing_package, nullptr);
|
||||
IMPLEMENT_DYNAMIC_ARG(Package*, clipboard_package, nullptr);
|
||||
|
||||
Package::Package()
|
||||
: fileStream(nullptr)
|
||||
, zipStream (nullptr)
|
||||
: zipStream (nullptr)
|
||||
{}
|
||||
|
||||
Package::~Package() {
|
||||
delete zipStream;
|
||||
delete fileStream;
|
||||
// remove any remaining temporary files
|
||||
FOR_EACH(f, files) {
|
||||
if (f.second.wasWritten()) {
|
||||
@@ -91,8 +88,7 @@ void Package::open(const String& n, bool fast) {
|
||||
void Package::reopen() {
|
||||
if (wxDirExists(filename)) {
|
||||
// make sure we have no zip open
|
||||
delete zipStream; zipStream = nullptr;
|
||||
delete fileStream; fileStream = nullptr;
|
||||
zipStream.reset();
|
||||
} else {
|
||||
// reopen only needed for zipfile
|
||||
openZipfile();
|
||||
@@ -154,40 +150,45 @@ void Package::clearKeepFlag() {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Package : inside
|
||||
|
||||
class FileInputStream_aux {
|
||||
protected:
|
||||
wxFileInputStream file_stream;
|
||||
inline FileInputStream_aux(const String& filename)
|
||||
: file_stream(filename)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Class that is a wxZipInputStream over a wxFileInput stream
|
||||
/** Note that wxFileInputStream is also a base class, because it must be constructed first
|
||||
*/
|
||||
class ZipFileInputStream : private wxFileInputStream, public wxZipInputStream {
|
||||
public:
|
||||
class ZipFileInputStream : private FileInputStream_aux, public wxZipInputStream {
|
||||
public:
|
||||
ZipFileInputStream(const String& filename)
|
||||
: FileInputStream_aux(filename)
|
||||
, wxZipInputStream(file_stream)
|
||||
{}
|
||||
ZipFileInputStream(const String& filename, wxZipEntry* entry)
|
||||
: wxFileInputStream(filename)
|
||||
, wxZipInputStream(static_cast<wxFileInputStream&>(*this))
|
||||
: FileInputStream_aux(filename)
|
||||
, wxZipInputStream(file_stream)
|
||||
{
|
||||
OpenEntry(*entry);
|
||||
}
|
||||
};
|
||||
|
||||
class BufferedFileInputStream_aux {
|
||||
protected:
|
||||
wxFileInputStream file_stream;
|
||||
inline BufferedFileInputStream_aux(const String& filename)
|
||||
: file_stream(filename)
|
||||
{}
|
||||
};
|
||||
/// A buffered version of wxFileInputStream
|
||||
/** 2007-08-24:
|
||||
* According to profiling this gives a significant speedup
|
||||
* Bringing the avarage run time of read_utf8_line from 186k to 54k (in cpu time units)
|
||||
*/
|
||||
class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBufferedInputStream {
|
||||
public:
|
||||
class BufferedFileInputStream : private FileInputStream_aux, public wxBufferedInputStream {
|
||||
public:
|
||||
inline BufferedFileInputStream(const String& filename)
|
||||
: BufferedFileInputStream_aux(filename)
|
||||
: FileInputStream_aux(filename)
|
||||
, wxBufferedInputStream(file_stream)
|
||||
{}
|
||||
};
|
||||
|
||||
InputStreamP Package::openIn(const String& file) {
|
||||
unique_ptr<wxInputStream> Package::openIn(const String& file) {
|
||||
if (!file.empty() && file.GetChar(0) == _('/')) {
|
||||
// absolute path, open file from another package
|
||||
Packaged* p = dynamic_cast<Packaged*>(this);
|
||||
@@ -200,16 +201,16 @@ InputStreamP Package::openIn(const String& file) {
|
||||
throw PackageError(_ERROR_2_("file not found package like", file, filename));
|
||||
}
|
||||
}
|
||||
InputStreamP stream;
|
||||
unique_ptr<wxInputStream> stream;
|
||||
if (it != files.end() && it->second.wasWritten()) {
|
||||
// written to this file, open the temp file
|
||||
stream = make_shared<BufferedFileInputStream>(it->second.tempName);
|
||||
stream = make_unique<BufferedFileInputStream>(it->second.tempName);
|
||||
} else if (wxFileExists(filename+_("/")+file)) {
|
||||
// a file in directory package
|
||||
stream = make_shared<BufferedFileInputStream>(filename+_("/")+file);
|
||||
stream = make_unique<BufferedFileInputStream>(filename+_("/")+file);
|
||||
} else if (wxFileExists(filename) && it != files.end() && it->second.zipEntry) {
|
||||
// a file in a zip archive
|
||||
stream = static_pointer_cast<wxZipInputStream>(make_shared<ZipFileInputStream>(filename, it->second.zipEntry));
|
||||
stream = make_unique<ZipFileInputStream>(filename, it->second.zipEntry);
|
||||
} else {
|
||||
// shouldn't happen, packaged changed by someone else since opening it
|
||||
throw FileNotFoundError(file, filename);
|
||||
@@ -221,8 +222,8 @@ InputStreamP Package::openIn(const String& file) {
|
||||
}
|
||||
}
|
||||
|
||||
OutputStreamP Package::openOut(const String& file) {
|
||||
return make_shared<wxFileOutputStream>(nameOut(file));
|
||||
unique_ptr<wxOutputStream> Package::openOut(const String& file) {
|
||||
return make_unique<wxFileOutputStream>(nameOut(file));
|
||||
}
|
||||
|
||||
String Package::nameOut(const String& file) {
|
||||
@@ -292,13 +293,13 @@ String Package::absoluteName(const String& file) {
|
||||
}
|
||||
}
|
||||
// Open a file that is in some package
|
||||
InputStreamP Package::openAbsoluteFile(const String& name) {
|
||||
unique_ptr<wxInputStream> Package::openAbsoluteFile(const String& name) {
|
||||
size_t pos = name.find_first_of(_('\1'));
|
||||
if (pos == String::npos) {
|
||||
// temp or dir file
|
||||
shared_ptr<wxFileInputStream> f = make_shared<wxFileInputStream>(name);
|
||||
if (!f->IsOk()) throw FileNotFoundError(_("<unknown>"), name);
|
||||
return f;
|
||||
auto stream = make_unique<wxFileInputStream>(name);
|
||||
if (!stream->IsOk()) throw FileNotFoundError(_("<unknown>"), name);
|
||||
return stream;
|
||||
} else {
|
||||
// packaged file, always in zip format
|
||||
Package p;
|
||||
@@ -355,12 +356,9 @@ void Package::openSubdir(const String& name) {
|
||||
|
||||
void Package::openZipfile() {
|
||||
// close old streams
|
||||
delete fileStream; fileStream = nullptr;
|
||||
delete zipStream; zipStream = nullptr;
|
||||
zipStream.reset();
|
||||
// open streams
|
||||
fileStream = new wxFileInputStream(filename);
|
||||
if (!fileStream->IsOk()) throw PackageError(_ERROR_1_("package not found", filename));
|
||||
zipStream = new wxZipInputStream(*fileStream);
|
||||
zipStream = make_unique<ZipFileInputStream>(filename);
|
||||
if (!zipStream->IsOk()) throw PackageError(_ERROR_1_("package not found", filename));
|
||||
// read zip entries
|
||||
loadZipStream();
|
||||
@@ -421,14 +419,13 @@ void Package::saveToZipfile(const String& saveAs, bool remove_unused, bool is_co
|
||||
} else {
|
||||
// changed file, or the old package was not a zipfile
|
||||
newZip->PutNextEntry(f.first);
|
||||
InputStreamP temp = openIn(f.first);
|
||||
newZip->Write(*temp);
|
||||
auto temp_stream = openIn(f.first);
|
||||
newZip->Write(*temp_stream);
|
||||
}
|
||||
}
|
||||
// close the old file
|
||||
if (!is_copy) {
|
||||
delete zipStream; zipStream = nullptr;
|
||||
delete fileStream; fileStream = nullptr;
|
||||
zipStream.reset();
|
||||
}
|
||||
} catch (Error e) {
|
||||
// when things go wrong delete the temp file
|
||||
@@ -503,11 +500,11 @@ Packaged::Packaged()
|
||||
, fully_loaded(true)
|
||||
{}
|
||||
|
||||
InputStreamP Packaged::openIconFile() {
|
||||
unique_ptr<wxInputStream> Packaged::openIconFile() {
|
||||
if (!icon_filename.empty()) {
|
||||
return openIn(icon_filename);
|
||||
} else {
|
||||
return InputStreamP();
|
||||
return unique_ptr<wxInputStream>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +523,8 @@ void Packaged::open(const String& package, bool just_header) {
|
||||
PROFILER(just_header ? _("open package header") : _("open package fully"));
|
||||
if (just_header) {
|
||||
// Read just the header (the part common to all Packageds)
|
||||
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName(), true);
|
||||
auto stream = openIn(typeName());
|
||||
Reader reader(*stream, this, absoluteFilename() + _("/") + typeName(), true);
|
||||
try {
|
||||
JustAsPackageProxy proxy(this);
|
||||
reader.handle_greedy(proxy);
|
||||
@@ -538,9 +536,11 @@ void Packaged::open(const String& package, bool just_header) {
|
||||
loadFully();
|
||||
}
|
||||
}
|
||||
|
||||
void Packaged::loadFully() {
|
||||
if (fully_loaded) return;
|
||||
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName());
|
||||
auto stream = openIn(typeName());
|
||||
Reader reader(*stream, this, absoluteFilename() + _("/") + typeName());
|
||||
try {
|
||||
reader.handle_greedy(*this);
|
||||
validate(reader.file_app_version);
|
||||
|
||||
+11
-12
@@ -100,11 +100,11 @@ class Package : public IntrusivePtrVirtualBase {
|
||||
// --------------------------------------------------- : Managing the inside of the package
|
||||
|
||||
/// Open an input stream for a file in the package.
|
||||
InputStreamP openIn(const String& file);
|
||||
unique_ptr<wxInputStream> openIn(const String& file);
|
||||
|
||||
/// Open an output stream for a file in the package.
|
||||
/// (changes are only committed with save())
|
||||
OutputStreamP openOut(const String& file);
|
||||
unique_ptr<wxOutputStream> openOut(const String& file);
|
||||
|
||||
/// Get a filename that can be written to to modfify a file in the package
|
||||
/// (changes are only committed with save())
|
||||
@@ -125,7 +125,7 @@ class Package : public IntrusivePtrVirtualBase {
|
||||
String absoluteName(const String& file);
|
||||
|
||||
/// Open a file given an absolute filename
|
||||
static InputStreamP openAbsoluteFile(const String& name);
|
||||
static unique_ptr<wxInputStream> openAbsoluteFile(const String& name);
|
||||
|
||||
// --------------------------------------------------- : Managing the inside of the package : Reader/writer
|
||||
|
||||
@@ -141,7 +141,8 @@ class Package : public IntrusivePtrVirtualBase {
|
||||
|
||||
template <typename T>
|
||||
void writeFile(const String& file, const T& obj, Version file_version) {
|
||||
Writer writer(openOut(file), file_version);
|
||||
auto stream = openOut(file);
|
||||
Writer writer(*stream, file_version);
|
||||
writer.handle(obj);
|
||||
}
|
||||
|
||||
@@ -182,10 +183,8 @@ class Package : public IntrusivePtrVirtualBase {
|
||||
private:
|
||||
/// All files in the package
|
||||
FileInfos files;
|
||||
/// Filestream for reading zip files
|
||||
wxFileInputStream* fileStream;
|
||||
/// Filestream for reading zip files
|
||||
wxZipInputStream* zipStream;
|
||||
/// Filestream/zipstream for reading zip files
|
||||
unique_ptr<wxZipInputStream> zipStream;
|
||||
|
||||
void loadZipStream();
|
||||
void openDirectory(bool fast = false);
|
||||
@@ -229,7 +228,7 @@ class Packaged : public Package {
|
||||
int position_hint; ///< A hint for the package list
|
||||
|
||||
/// Get an input stream for the package icon, if there is any
|
||||
InputStreamP openIconFile();
|
||||
unique_ptr<wxInputStream> openIconFile();
|
||||
|
||||
/// Open a package, and read the data
|
||||
/** if just_header is true, then the package is not fully parsed.
|
||||
@@ -289,9 +288,9 @@ intrusive_ptr<T> open_package(const String& filename) {
|
||||
|
||||
// This is here because it uses dynamic_cast and must be to a complete type.
|
||||
template <typename T>
|
||||
inline void Package::readFile(const String& file, T& obj)
|
||||
{
|
||||
Reader reader(openIn(file), dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
|
||||
inline void Package::readFile(const String& file, T& obj) {
|
||||
auto stream = openIn(file);
|
||||
Reader reader(*stream, dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
|
||||
try {
|
||||
reader.handle_greedy(obj);
|
||||
} catch (const ParseError& err) {
|
||||
|
||||
@@ -99,7 +99,7 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out)
|
||||
}
|
||||
}
|
||||
|
||||
InputStreamP PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
|
||||
unique_ptr<wxInputStream> PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
|
||||
if (!name.empty() && name.GetChar(0) == _('/')) {
|
||||
// absolute name; break name
|
||||
size_t start = name.find_first_not_of(_("/\\"), 1); // allow "//package/name" from incorrect scripts
|
||||
@@ -339,16 +339,17 @@ void PackageDirectory::loadDatabase() {
|
||||
String filename = databaseFile();
|
||||
if (wxFileExists(filename)) {
|
||||
// packages file not existing is not an error
|
||||
shared_ptr<wxFileInputStream> file = make_shared<wxFileInputStream>(filename);
|
||||
if (!file->Ok()) return; // failure is not an error
|
||||
Reader reader(file, nullptr, filename);
|
||||
wxFileInputStream file_stream = {filename};
|
||||
if (!file_stream.Ok()) return; // failure is not an error
|
||||
Reader reader(file_stream, nullptr, filename);
|
||||
reader.handle_greedy(*this);
|
||||
sort(packages.begin(), packages.end(), compare_name);
|
||||
}
|
||||
}
|
||||
|
||||
void PackageDirectory::saveDatabase() {
|
||||
Writer writer(make_shared<wxFileOutputStream>(databaseFile()), app_version);
|
||||
wxFileOutputStream stream(databaseFile());
|
||||
Writer writer(stream, app_version);
|
||||
writer.handle(*this);
|
||||
}
|
||||
String PackageDirectory::databaseFile() {
|
||||
@@ -391,13 +392,13 @@ bool PackageDirectory::actual_install(const InstallablePackage& package, const S
|
||||
String local_file = install_dir + file.substr(name.length());
|
||||
create_parent_dirs(local_file);
|
||||
// copy file
|
||||
InputStreamP is = installer.openIn(file);
|
||||
wxFileOutputStream os (local_file);
|
||||
if (!os.IsOk()) {
|
||||
auto in_stream = installer.openIn(file);
|
||||
wxFileOutputStream out_stream(local_file);
|
||||
if (!out_stream.IsOk()) {
|
||||
int act = wxMessageBox(_ERROR_1_("cannot create file", file), _TITLE_("cannot create file"), wxICON_ERROR | wxYES_NO);
|
||||
if (act == wxNO) return false;
|
||||
}
|
||||
os.Write(*is);
|
||||
out_stream.Write(*in_stream);
|
||||
}
|
||||
// update package database
|
||||
// TODO: bless the package?
|
||||
|
||||
@@ -148,7 +148,7 @@ class PackageManager {
|
||||
* this is to force people to fill in the dependencies
|
||||
* Afterwards, package will be set to the package the file is opened from
|
||||
*/
|
||||
InputStreamP openFileFromPackage(Packaged*& package, const String& name);
|
||||
unique_ptr<wxInputStream> openFileFromPackage(Packaged*& package, const String& name);
|
||||
|
||||
/// Get a filename to open from a package
|
||||
/** WARNING: this is a bit of a hack, since not all package types support names in this way.
|
||||
|
||||
+15
-28
@@ -21,33 +21,20 @@ IMPLEMENT_DYNAMIC_ARG(ReaderPragmaHandler,reader_pragma_handler,nullptr);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Reader
|
||||
|
||||
Reader::Reader(const InputStreamP& input, Packaged* package, const String& filename, bool ignore_invalid)
|
||||
Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid)
|
||||
: indent(0), expected_indent(0), state(OUTSIDE)
|
||||
, ignore_invalid(ignore_invalid)
|
||||
, filename(filename), package(package), line_number(0), previous_line_number(0)
|
||||
, input(input)
|
||||
{
|
||||
assert(input);
|
||||
assert(input->IsOk());
|
||||
eat_utf8_bom(*input);
|
||||
assert(input.IsOk());
|
||||
eat_utf8_bom(input);
|
||||
moveNext();
|
||||
handleAppVersion();
|
||||
}
|
||||
|
||||
Reader::Reader(Reader* parent, Packaged* pkg, const String& filename, bool ignore_invalid)
|
||||
: indent(0), expected_indent(0), state(OUTSIDE)
|
||||
, ignore_invalid(ignore_invalid)
|
||||
, filename(filename), package(pkg), line_number(0), previous_line_number(0)
|
||||
, input(package_manager.openFileFromPackage(package, filename))
|
||||
{
|
||||
assert(input);
|
||||
eat_utf8_bom(*input);
|
||||
moveNext();
|
||||
// in an included file, use the app version of the parent if we have none
|
||||
handleAppVersion();
|
||||
if (file_app_version == 0) {
|
||||
file_app_version = parent->file_app_version;
|
||||
}
|
||||
unique_ptr<wxInputStream> Reader::openIncludedFile() {
|
||||
return package_manager.openFileFromPackage(package, value);
|
||||
}
|
||||
|
||||
void Reader::addAlias(Version end_version, const Char* a, const Char* b) {
|
||||
@@ -125,11 +112,11 @@ void Reader::moveNext() {
|
||||
key.clear();
|
||||
indent = -1; // if no line is read it never has the expected indentation
|
||||
// repeat until we have a good line
|
||||
while (key.empty() && !input->Eof()) {
|
||||
while (key.empty() && !input.Eof()) {
|
||||
readLine();
|
||||
}
|
||||
// did we reach the end of the file?
|
||||
if (key.empty() && input->Eof()) {
|
||||
if (key.empty() && input.Eof()) {
|
||||
line_number += 1;
|
||||
indent = -1;
|
||||
}
|
||||
@@ -216,7 +203,7 @@ void Reader::readLine(bool in_string) {
|
||||
line_number += 1;
|
||||
// We have to do our own line reading, because wxTextInputStream is insane
|
||||
try {
|
||||
line = read_utf8_line(*input);
|
||||
line = read_utf8_line(input);
|
||||
} catch (const ParseError& e) {
|
||||
throw ParseError(e.what() + String(_(" on line ")) << line_number);
|
||||
}
|
||||
@@ -304,7 +291,7 @@ const String& Reader::getValue() {
|
||||
// read all lines that are indented enough
|
||||
readLine(true);
|
||||
previous_line_number = line_number;
|
||||
while (indent >= expected_indent && !input->Eof()) {
|
||||
while (indent >= expected_indent && !input.Eof()) {
|
||||
previous_value.resize(previous_value.size() + pending_newlines, _('\n'));
|
||||
pending_newlines = 0;
|
||||
previous_value += line.substr(expected_indent); // strip expected indent
|
||||
@@ -312,15 +299,15 @@ const String& Reader::getValue() {
|
||||
readLine(true);
|
||||
pending_newlines++;
|
||||
// skip empty lines that are not indented enough
|
||||
} while(trim(line).empty() && indent < expected_indent && !input->Eof());
|
||||
} while(trim(line).empty() && indent < expected_indent && !input.Eof());
|
||||
}
|
||||
// moveNext(), but without the initial readLine()
|
||||
state = HANDLED;
|
||||
while (key.empty() && !input->Eof()) {
|
||||
while (key.empty() && !input.Eof()) {
|
||||
readLine();
|
||||
}
|
||||
// did we reach the end of the file?
|
||||
if (key.empty() && input->Eof()) {
|
||||
if (key.empty() && input.Eof()) {
|
||||
line_number += 1;
|
||||
indent = -1;
|
||||
}
|
||||
@@ -400,9 +387,9 @@ template <> void Reader::handle(FileName& f) {
|
||||
// copy file into current package
|
||||
try {
|
||||
String packaged_name = clipboard_package()->newFileName(_("image"),_("")); // a new unique name in the package, assume it's an image
|
||||
OutputStreamP out = clipboard_package()->openOut(packaged_name);
|
||||
InputStreamP in = Package::openAbsoluteFile(str);
|
||||
out->Write(*in); // copy
|
||||
auto out_stream = clipboard_package()->openOut(packaged_name);
|
||||
auto in_stream = Package::openAbsoluteFile(str);
|
||||
out_stream->Write(*in_stream); // copy
|
||||
f.assign(packaged_name);
|
||||
} catch (Error const&) {
|
||||
// ignore errors
|
||||
|
||||
+12
-9
@@ -20,9 +20,6 @@ class Packaged;
|
||||
|
||||
// ----------------------------------------------------------------------------- : Reader
|
||||
|
||||
typedef wxInputStream InputStream;
|
||||
typedef shared_ptr<wxInputStream> InputStreamP;
|
||||
|
||||
/// The Reader can be used for reading (deserializing) objects
|
||||
/** This class makes use of the reflection functionality, in effect
|
||||
* an object tells the Reader what fields it would like to read.
|
||||
@@ -37,12 +34,12 @@ class Reader {
|
||||
/** Used for "include file" keys.
|
||||
* package can be nullptr
|
||||
*/
|
||||
Reader(Reader* parent, Packaged* package, const String& filename, bool ignore_invalid = false);
|
||||
//Reader(Reader* parent, Packaged* package, const String& filename, bool ignore_invalid = false);
|
||||
public:
|
||||
/// Construct a reader that reads from the given input stream
|
||||
/** filename is used only for error messages
|
||||
*/
|
||||
Reader(const InputStreamP& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
|
||||
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
|
||||
|
||||
~Reader() { showWarnings(); }
|
||||
|
||||
@@ -119,7 +116,7 @@ class Reader {
|
||||
// --------------------------------------------------- : Data
|
||||
/// App version this file was made with
|
||||
Version file_app_version;
|
||||
private:
|
||||
private:
|
||||
/// The line we read
|
||||
String line;
|
||||
/// The key and value of the last line we read
|
||||
@@ -156,7 +153,7 @@ class Reader {
|
||||
/// Line number of the previous_line
|
||||
int previous_line_number;
|
||||
/// Input stream we are reading from
|
||||
InputStreamP input;
|
||||
wxInputStream& input;
|
||||
/// Accumulated warning messages
|
||||
String warnings;
|
||||
|
||||
@@ -182,14 +179,20 @@ class Reader {
|
||||
template <typename T>
|
||||
void unknownKey(T& v) {
|
||||
if (key == _("include_file")) {
|
||||
Reader reader(this, package, value, ignore_invalid);
|
||||
reader.handle_greedy(v);
|
||||
auto stream = openIncludedFile();
|
||||
Reader sub_reader(*stream, package, value, ignore_invalid);
|
||||
if (sub_reader.file_app_version == 0) {
|
||||
// in an included file, use the app version of the parent if there is none
|
||||
sub_reader.file_app_version = file_app_version;
|
||||
}
|
||||
sub_reader.handle_greedy(v);
|
||||
moveNext();
|
||||
} else {
|
||||
unknownKey();
|
||||
}
|
||||
}
|
||||
void unknownKey();
|
||||
unique_ptr<wxInputStream> openIncludedFile();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Container types
|
||||
|
||||
@@ -17,10 +17,10 @@ using boost::tribool;
|
||||
|
||||
// ----------------------------------------------------------------------------- : Writer
|
||||
|
||||
Writer::Writer(const OutputStreamP& output, Version file_app_version)
|
||||
Writer::Writer(OutputStream& output, Version file_app_version)
|
||||
: indentation(0)
|
||||
, output(output)
|
||||
, stream(*output, wxEOL_UNIX, wxMBConvUTF8())
|
||||
, stream(output, wxEOL_UNIX, wxMBConvUTF8())
|
||||
{
|
||||
stream.WriteString(BYTE_ORDER_MARK);
|
||||
handle(_("mse_version"), file_app_version);
|
||||
|
||||
@@ -19,14 +19,11 @@ DECLARE_POINTER_TYPE(StyleSheet);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Writer
|
||||
|
||||
typedef wxOutputStream OutputStream;
|
||||
typedef shared_ptr<wxOutputStream> OutputStreamP;
|
||||
|
||||
/// The Writer can be used for writing (serializing) objects
|
||||
class Writer {
|
||||
public:
|
||||
/// Construct a writer that writes to the given output stream
|
||||
Writer(const OutputStreamP& output, Version file_app_version);
|
||||
Writer(OutputStream& output, Version file_app_version);
|
||||
|
||||
/// Tell the reflection code we are not reading
|
||||
inline bool reading() const { return false; }
|
||||
@@ -81,7 +78,7 @@ class Writer {
|
||||
vector<const Char*> pending_opened;
|
||||
|
||||
/// Output stream we are writing to
|
||||
OutputStreamP output;
|
||||
OutputStream& output;
|
||||
/// Text stream wrapping the output stream
|
||||
wxTextOutputStream stream;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user