From e1b8089be727f651fc2022d6e7ff775047730e85 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 17 Jan 2021 12:41:50 +0200 Subject: [PATCH] Implement proper copy semantics All classes are now either safe to copy or are marked noncopyable. --- source/argumentstore.cpp | 43 +++++++++++++++++++++ source/argumentstore.h | 6 +++ source/collection.h | 5 +-- source/input.h | 3 +- source/loadabletyperegistry.h | 2 +- source/loader.h | 2 +- source/output.h | 3 +- source/packsource.cpp | 71 +++++++++++++++++++++++++++++++++++ source/packsource.h | 13 +++++++ source/parser.h | 3 +- source/parsermode.h | 3 +- source/writer.h | 3 +- source/writermode.h | 4 +- 13 files changed, 150 insertions(+), 11 deletions(-) diff --git a/source/argumentstore.cpp b/source/argumentstore.cpp index 532d66a..22cb11f 100644 --- a/source/argumentstore.cpp +++ b/source/argumentstore.cpp @@ -1,5 +1,8 @@ +#include #include "argumentstore.h" +using namespace std; + namespace Msp { namespace DataFile { @@ -19,7 +22,30 @@ ArgumentStore::ArgumentStore(const StatementInfo &n): } } +ArgumentStore::ArgumentStore(const ArgumentStore &other): + info(other.info), + store(new char[info.args_size]) +{ + copy_from(other.store); +} + +ArgumentStore &ArgumentStore::operator=(const ArgumentStore &other) +{ + if(&other.info!=&info) + throw invalid_argument("ArgumentStore::operator="); + + destroy(); + copy_from(other.store); + + return *this; +} + ArgumentStore::~ArgumentStore() +{ + destroy(); +} + +void ArgumentStore::destroy() { for(unsigned i=0; i(other+info.arg_offsets[i])); + break; + case SymbolType::signature: + new(store+info.arg_offsets[i]) SymbolType::Store(*reinterpret_cast(other+info.arg_offsets[i])); + break; + default: + copy(other+info.arg_offsets[i], other+(i+1 diff --git a/source/collection.h b/source/collection.h index 87af3a2..38d9321 100644 --- a/source/collection.h +++ b/source/collection.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "collectionsource.h" #include "loader.h" @@ -49,7 +50,7 @@ that are not present. Items retrieted from the fallback collection are shared between the collections, and are only deleted when all collections in the chain have been destroyed. */ -class Collection +class Collection: private NonCopyable { public: /** @@ -91,8 +92,6 @@ private: SourceList sources; Collection *fallback; - Collection(const Collection &); - Collection &operator=(const Collection &); public: Collection(); virtual ~Collection(); diff --git a/source/input.h b/source/input.h index a9c96f4..d30abd6 100644 --- a/source/input.h +++ b/source/input.h @@ -1,12 +1,13 @@ #ifndef MSP_DATAFILE_INPUT_H_ #define MSP_DATAFILE_INPUT_H_ +#include #include namespace Msp { namespace DataFile { -class Input +class Input: private NonCopyable { private: IO::Base *in; diff --git a/source/loadabletyperegistry.h b/source/loadabletyperegistry.h index ace98cb..7b027cd 100644 --- a/source/loadabletyperegistry.h +++ b/source/loadabletyperegistry.h @@ -16,7 +16,7 @@ must be given as a template parameter, as well as a helper template struct to handle the actual adding of keywords. */ template class A> -class LoadableTypeRegistry: public NonCopyable +class LoadableTypeRegistry: private NonCopyable { private: class TypeBase diff --git a/source/loader.h b/source/loader.h index 5dac2e6..9736d26 100644 --- a/source/loader.h +++ b/source/loader.h @@ -33,7 +33,7 @@ destructor. See also classes ObjectLoader and CollectionObjectLoader in objectloader.h. */ -class Loader +class Loader: private NonCopyable { protected: typedef std::map ActionMap; diff --git a/source/output.h b/source/output.h index 13dc829..bd75651 100644 --- a/source/output.h +++ b/source/output.h @@ -1,12 +1,13 @@ #ifndef MSP_DATAFILE_OUTPUT_H_ #define MSP_DATAFILE_OUTPUT_H_ +#include #include namespace Msp { namespace DataFile { -class Output +class Output: private NonCopyable { private: IO::Base *out; diff --git a/source/packsource.cpp b/source/packsource.cpp index ec7232a..b9f6016 100644 --- a/source/packsource.cpp +++ b/source/packsource.cpp @@ -18,6 +18,31 @@ void delete_io(Msp::IO::Base *io) namespace Msp { namespace DataFile { +PackSource::PackSource(const PackSource &other): + packs(other.packs), + files(other.files), + objects(other.objects) +{ + translate_maps(other); +} + +PackSource &PackSource::operator=(const PackSource &other) +{ + packs = list(other.packs.begin(), other.packs.end()); + files = other.files; + objects = other.objects; + translate_maps(other); + return *this; +} + +void PackSource::translate_maps(const PackSource &other) +{ + for(list::const_iterator i=packs.begin(), j=other.packs.begin(); (i!=packs.end() && j!=other.packs.end()); ++i, ++j) + i->translate_files(files, *j); + for(FileMap::const_iterator i=files.begin(), j=other.files.begin(); (i!=files.end() && j!=other.files.end()); ++i, ++j) + i->second->translate_objects(objects, *j->second); +} + void PackSource::add_pack_file(const string &fn) { add_pack_file(fn, string()); @@ -142,6 +167,15 @@ PackSource::Pack::Pack(IO::Seekable *i, const string &fn): base_offset(0) { } +PackSource::Pack::Pack(const Pack &other): + filename(other.filename), + io(other.io), + base_offset(other.base_offset) +{ + for(list::const_iterator i=other.files.begin(); i!=other.files.end(); ++i) + files.push_back(File(*i, *this)); +} + void PackSource::Pack::collect_files(FileMap &fm, const string &filter) const { if(filter.empty()) @@ -158,6 +192,16 @@ void PackSource::Pack::collect_files(FileMap &fm, const string &filter) const } } +void PackSource::Pack::translate_files(FileMap &fm, const Pack &source) const +{ + for(list::const_iterator i=files.begin(), j=source.files.begin(); (i!=files.end() && j!=source.files.end()); ++i, ++j) + { + FileMap::iterator k = fm.find(i->get_filename()); + if(k!=fm.end() && k->second==&*j) + k->second = &*i; + } +} + PackSource::File::File(const Pack &p, const string &fn): pack(p), @@ -167,6 +211,17 @@ PackSource::File::File(const Pack &p, const string &fn): collection(false) { } +PackSource::File::File(const File &other, const Pack &p): + pack(p), + filename(other.filename), + offset(other.offset), + length(other.length), + collection(other.collection) +{ + for(list::const_iterator i=other.objects.begin(); i!=other.objects.end(); ++i) + objects.push_back(Object(*i, *this)); +} + RefPtr PackSource::File::open() const { if(pack.get_io()) @@ -200,6 +255,16 @@ void PackSource::File::collect_objects(ObjectMap &objs) const objs[i->get_name()] = &*i; } +void PackSource::File::translate_objects(ObjectMap &objs, const File &source) const +{ + for(list::const_iterator i=objects.begin(), j=source.objects.begin(); (i!=objects.end() && j!=source.objects.end()); ++i, ++j) + { + ObjectMap::iterator k = objs.find(i->get_name()); + if(k!=objs.end() && k->second==&*j) + k->second = &*i; + } +} + PackSource::Object::Object(const File &f, const string &n, const string &k): file(f), @@ -207,6 +272,12 @@ PackSource::Object::Object(const File &f, const string &n, const string &k): keyword(k) { } +PackSource::Object::Object(const Object &other, const File &f): + file(f), + name(other.name), + keyword(other.keyword) +{ } + PackSource::Pack::Loader::Loader(Pack &p): ObjectLoader(p) diff --git a/source/packsource.h b/source/packsource.h index 56590b1..3694a3b 100644 --- a/source/packsource.h +++ b/source/packsource.h @@ -1,6 +1,7 @@ #ifndef MSP_DATAFILE_PACKSOURCE_H_ #define MSP_DATAFILE_PACKSOURCE_H_ +#include #include #include "collectionsource.h" #include "objectloader.h" @@ -54,12 +55,14 @@ private: public: Pack(IO::Seekable *, const std::string &); + Pack(const Pack &); const std::string &get_filename() const { return filename; } IO::Seekable *get_io() const { return io; } IO::SeekOffset get_base_offset() const { return base_offset; } void collect_files(FileMap &, const std::string &) const; + void translate_files(FileMap &, const Pack &) const; }; class File @@ -84,6 +87,7 @@ private: public: File(const Pack &, const std::string &); + File(const File &, const Pack &); RefPtr open() const; const std::string &get_filename() const { return filename; } @@ -92,6 +96,7 @@ private: bool is_collection() const { return collection; } void collect_objects(ObjectMap &) const; + void translate_objects(ObjectMap &, const File &) const; }; class Object @@ -103,6 +108,7 @@ private: public: Object(const File &, const std::string &, const std::string &); + Object(const Object &, const File &); const File &get_file() const { return file; } const std::string &get_name() const { return name; } @@ -113,6 +119,13 @@ private: FileMap files; ObjectMap objects; +public: + PackSource() { } + PackSource(const PackSource &); + PackSource &operator=(const PackSource &); +private: + void translate_maps(const PackSource &); + public: /// Adds a pack file to load objects from. The index is read immediately. void add_pack_file(const std::string &); diff --git a/source/parser.h b/source/parser.h index 1437190..d187960 100644 --- a/source/parser.h +++ b/source/parser.h @@ -2,6 +2,7 @@ #define MSP_DATAFILE_PARSER_H_ #include +#include #include "input.h" namespace Msp { @@ -18,7 +19,7 @@ Frontend for loading datafiles. Handles switching between text and binary formats. A Parser evaluates into a boolean value indicating whether more statements may be read. */ -class Parser +class Parser: private NonCopyable { private: Input in; diff --git a/source/parsermode.h b/source/parsermode.h index 491647e..5c9dece 100644 --- a/source/parsermode.h +++ b/source/parsermode.h @@ -1,6 +1,7 @@ #ifndef MSP_DATAFILE_PARSERMODE_H_ #define MSP_DATAFILE_PARSERMODE_H_ +#include #include "statement.h" namespace Msp { @@ -13,7 +14,7 @@ class LoaderAction; /** Base class for parse modes. */ -class ParserMode +class ParserMode: private NonCopyable { protected: Input ∈ diff --git a/source/writer.h b/source/writer.h index 18fb314..c209947 100644 --- a/source/writer.h +++ b/source/writer.h @@ -2,6 +2,7 @@ #define MSP_DATAFILE_WRITER_H_ #include +#include #include #include "output.h" @@ -14,7 +15,7 @@ class WriterMode; /** Frontend for writing data. */ -class Writer +class Writer: private NonCopyable { private: Output out; diff --git a/source/writermode.h b/source/writermode.h index 05058ab..cc37710 100644 --- a/source/writermode.h +++ b/source/writermode.h @@ -1,13 +1,15 @@ #ifndef MSP_DATAFILE_WRITERMODE_H_ #define MSP_DATAFILE_WRITERMODE_H_ +#include + namespace Msp { namespace DataFile { class Output; class Statement; -class WriterMode +class WriterMode: private NonCopyable { protected: Output &out; -- 2.45.2