From: Richard Kreckel Date: Sun, 22 Sep 2019 17:18:19 +0000 (+0200) Subject: Fix unarchiving empty containers. X-Git-Tag: release_1-7-7~3 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=9f3e78a13c72ca73ade4d0829186edcdc1c1b2a0 Fix unarchiving empty containers. The bug was reported by Vladimir V. Kisil , see . --- diff --git a/ginac/archive.cpp b/ginac/archive.cpp index eb50e865..5fa5d1f5 100644 --- a/ginac/archive.cpp +++ b/ginac/archive.cpp @@ -357,17 +357,17 @@ bool archive_node::has_same_ex_as(const archive_node &other) const } archive_node::archive_node_cit - archive_node::find_first(const std::string &name) const -{ +archive_node::find_first(const std::string &name) const +{ archive_atom name_atom = a.atomize(name); for (auto i=props.begin(); i!=props.end(); ++i) if (i->name == name_atom) return i; - return props.end();; + return props.end(); } archive_node::archive_node_cit - archive_node::find_last(const std::string &name) const +archive_node::find_last(const std::string &name) const { archive_atom name_atom = a.atomize(name); for (auto i=props.end(); i!=props.begin();) { @@ -378,6 +378,23 @@ archive_node::archive_node_cit return props.end(); } +archive_node::archive_node_cit_range +archive_node::find_property_range(const std::string &name1, const std::string &name2) const +{ + archive_atom name1_atom = a.atomize(name1), + name2_atom = a.atomize(name2); + archive_node_cit_range range = {props.end(), props.end()}; + for (auto i=props.begin(); i!=props.end(); ++i) { + if (i->name == name1_atom && range.begin == props.end()) { + range.begin = i; + } + if (i->name == name2_atom && range.begin != props.end()) { + range.end = i + 1; + } + } + return range; +} + void archive_node::add_bool(const std::string &name, bool value) { props.push_back(property(a.atomize(name), PTYPE_BOOL, value)); @@ -455,8 +472,7 @@ bool archive_node::find_string(const std::string &name, std::string &ret, unsign return false; } -void archive_node::find_ex_by_loc(archive_node_cit loc, ex &ret, lst &sym_lst) - const +void archive_node::find_ex_by_loc(archive_node_cit loc, ex &ret, lst &sym_lst) const { ret = a.get_node(loc->value).unarchive(sym_lst); } @@ -517,7 +533,7 @@ void archive_node::get_properties(propinfovector &v) const if (!found) v.push_back(property_info(type, name)); i++; - } + } } static synthesize_func find_factory_fcn(const std::string& name) diff --git a/ginac/archive.h b/ginac/archive.h index 53c45437..c3314f13 100644 --- a/ginac/archive.h +++ b/ginac/archive.h @@ -82,6 +82,9 @@ public: unsigned value; /**< Stored value. */ }; typedef std::vector::const_iterator archive_node_cit; + struct archive_node_cit_range { + archive_node_cit begin, end; + }; archive_node(archive &ar) : a(ar), has_expression(false) {} archive_node(archive &ar, const ex &expr); @@ -113,17 +116,22 @@ public: bool find_string(const std::string &name, std::string &ret, unsigned index = 0) const; /** Find the location in the vector of properties of the first/last - * property with a given name. */ + * property with a given name. */ archive_node_cit find_first(const std::string &name) const; archive_node_cit find_last(const std::string &name) const; + /** Find a range of locations in the vector of properties. The result + * begins at the first property with name1 and ends one past the last + * property with name2. */ + archive_node_cit_range find_property_range(const std::string &name1, const std::string &name2) const; + /** Retrieve property of type "ex" from node. * @return "true" if property was found, "false" otherwise */ bool find_ex(const std::string &name, ex &ret, lst &sym_lst, unsigned index = 0) const; /** Retrieve property of type "ex" from the node if it is known - * that this node in fact contains such a property at the given - * location. This is much more efficient than the preceding function. */ + * that this node in fact contains such a property at the given + * location. This is much more efficient than the preceding function. */ void find_ex_by_loc(archive_node_cit loc, ex &ret, lst &sym_lst) const; /** Retrieve property of type "ex" from node, returning the node of @@ -271,14 +279,14 @@ public: /** Retrieve expression from archive by index. * @param sym_lst list of pre-defined symbols * @param index index of expression - * @see count_expressions */ + * @see count_expressions */ ex unarchive_ex(const lst &sym_lst, unsigned index = 0) const; /** Retrieve expression and its name from archive by index. * @param sym_lst list of pre-defined symbols * @param name receives the name of the expression * @param index index of expression - * @see count_expressions */ + * @see count_expressions */ ex unarchive_ex(const lst &sym_lst, std::string &name, unsigned index = 0) const; /** Return number of archived expressions. */ diff --git a/ginac/container.h b/ginac/container.h index 960f0729..4360bcc0 100644 --- a/ginac/container.h +++ b/ginac/container.h @@ -212,14 +212,12 @@ public: inherited::read_archive(n, sym_lst); setflag(get_default_flags()); - archive_node::archive_node_cit first = n.find_first("seq"); - archive_node::archive_node_cit last = n.find_last("seq"); - ++last; - this->reserve(this->seq, last - first); - for (archive_node::archive_node_cit i=first; ireserve(this->seq, range.end - range.begin); + for (archive_node::archive_node_cit i=range.begin; iseq.push_back(e); + this->seq.emplace_back(e); } } diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index a1361532..59bd8316 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -112,17 +112,15 @@ expairseq::expairseq(epvector && vp, const ex &oc, bool do_index_renaming) void expairseq::read_archive(const archive_node &n, lst &sym_lst) { inherited::read_archive(n, sym_lst); - auto first = n.find_first("rest"); - auto last = n.find_last("coeff"); - ++last; - seq.reserve((last-first)/2); + auto range = n.find_property_range("rest", "coeff"); + seq.reserve((range.end-range.begin)/2); - for (auto loc = first; loc < last;) { + for (auto loc = range.begin; loc < range.end;) { ex rest; ex coeff; n.find_ex_by_loc(loc++, rest, sym_lst); n.find_ex_by_loc(loc++, coeff, sym_lst); - seq.push_back(expair(rest, coeff)); + seq.emplace_back(expair(rest, coeff)); } n.find_ex("overall_coeff", overall_coeff, sym_lst); diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index fb675060..a1be78cf 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -140,13 +140,11 @@ void matrix::read_archive(const archive_node &n, lst &sym_lst) m.reserve(row * col); // XXX: default ctor inserts a zero element, we need to erase it here. m.pop_back(); - auto first = n.find_first("m"); - auto last = n.find_last("m"); - ++last; - for (auto i=first; i != last; ++i) { + auto range = n.find_property_range("m", "m"); + for (auto i=range.begin; i != range.end; ++i) { ex e; n.find_ex_by_loc(i, e, sym_lst); - m.push_back(e); + m.emplace_back(e); } } GINAC_BIND_UNARCHIVER(matrix); diff --git a/ginac/pseries.cpp b/ginac/pseries.cpp index 4dba5129..b064a202 100644 --- a/ginac/pseries.cpp +++ b/ginac/pseries.cpp @@ -119,17 +119,15 @@ pseries::pseries(const ex &rel_, epvector &&ops_) void pseries::read_archive(const archive_node &n, lst &sym_lst) { inherited::read_archive(n, sym_lst); - auto first = n.find_first("coeff"); - auto last = n.find_last("power"); - ++last; - seq.reserve((last-first)/2); + auto range = n.find_property_range("coeff", "power"); + seq.reserve((range.end-range.begin)/2); - for (auto loc = first; loc < last;) { + for (auto loc = range.begin; loc < range.end;) { ex rest; ex coeff; n.find_ex_by_loc(loc++, rest, sym_lst); n.find_ex_by_loc(loc++, coeff, sym_lst); - seq.push_back(expair(rest, coeff)); + seq.emplace_back(expair(rest, coeff)); } n.find_ex("var", var, sym_lst);