mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
Turn psring iterator into a real forward iterator that works with standard algorithms.
There are a few changes to achieve this: * Rename to const_iterator since it's immutable * Typedef iterator to const_iterator for now as there's no mutable iterator * Add default constrcutor and operator-> required by concept, const-qualify operators * Remove operator+ and operator+= since it's not a random-access iterator (use std::next and std::advance instead) * Return reference/pointer to a proxy rather than a code_t value from opertator*/operator-> The final change is required to meet the requirement that operator* for two equivalent forward iterators return an equivalent reference. The pstring doesn't actually contain a sequence of code_t, so there's no way to return a reference to code_t directly. Instead, a reference to a proxy object aliased on the string storage is returned. The proxy is implicitly convertible to code_t. The most noticeable side effect is that auto c = *s.begin() or for (auto c : s) won't work. You need to do for (auto &c : s) or for (code_t c : s) instead.
This commit is contained in:
parent
35b673ea45
commit
5e8fefbb12
@ -100,7 +100,7 @@ void setup_t::register_model(const pstring &model_in)
|
||||
if (pos == model_in.end())
|
||||
log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
|
||||
pstring model = model_in.left(pos).trim().ucase();
|
||||
pstring def = model_in.substr(pos + 1).trim();
|
||||
pstring def = model_in.substr(std::next(pos, 1)).trim();
|
||||
if (!m_models.insert({model, def}).second)
|
||||
log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
|
||||
}
|
||||
@ -818,11 +818,11 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
|
||||
log().fatal(MF_1_MODEL_NOT_FOUND, model_in);
|
||||
}
|
||||
|
||||
pstring remainder=model.substr(pos+1).trim();
|
||||
pstring remainder=model.substr(std::next(pos, 1)).trim();
|
||||
if (!remainder.endsWith(")"))
|
||||
log().fatal(MF_1_MODEL_ERROR_1, model);
|
||||
// FIMXE: Not optimal
|
||||
remainder = remainder.left(remainder.begin() + (remainder.len() - 1));
|
||||
remainder = remainder.left(std::next(remainder.begin(), (remainder.len() - 1)));
|
||||
|
||||
std::vector<pstring> pairs(plib::psplit(remainder," ", true));
|
||||
for (pstring &pe : pairs)
|
||||
@ -830,7 +830,7 @@ void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
|
||||
auto pose = pe.find("=");
|
||||
if (pose == pe.end())
|
||||
log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
|
||||
map[pe.left(pose).ucase()] = pe.substr(pose+1);
|
||||
map[pe.left(pose).ucase()] = pe.substr(std::next(pose, 1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -854,7 +854,7 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
|
||||
pstring tmp = model_value_str(map, entity);
|
||||
|
||||
nl_double factor = NL_FCONST(1.0);
|
||||
auto p = tmp.begin() + (tmp.len() - 1);
|
||||
auto p = std::next(tmp.begin(), (tmp.len() - 1));
|
||||
switch (*p)
|
||||
{
|
||||
case 'M': factor = 1e6; break;
|
||||
@ -870,7 +870,7 @@ nl_double setup_t::model_value(detail::model_map_t &map, const pstring &entity)
|
||||
log().fatal(MF_1_UNKNOWN_NUMBER_FACTOR_IN_1, entity);
|
||||
}
|
||||
if (factor != NL_FCONST(1.0))
|
||||
tmp = tmp.left(tmp.begin() + (tmp.len() - 1));
|
||||
tmp = tmp.left(std::next(tmp.begin(), (tmp.len() - 1)));
|
||||
return tmp.as_double() * factor;
|
||||
}
|
||||
|
||||
@ -976,7 +976,7 @@ void setup_t::register_define(pstring defstr)
|
||||
{
|
||||
auto p = defstr.find("=");
|
||||
if (p != defstr.end())
|
||||
register_define(defstr.left(p), defstr.substr(p+1));
|
||||
register_define(defstr.left(p), defstr.substr(std::next(p, 1)));
|
||||
else
|
||||
register_define(defstr, "1");
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ static int get_prio(pstring v)
|
||||
{
|
||||
if (v == "(" || v == ")")
|
||||
return 1;
|
||||
else if (v.left(v.begin()+1) >= "a" && v.left(v.begin()+1) <= "z")
|
||||
else if (v.left(std::next(v.begin(),1)) >= "a" && v.left(std::next(v.begin(),1)) <= "z")
|
||||
return 0;
|
||||
else if (v == "*" || v == "/")
|
||||
return 20;
|
||||
|
@ -133,8 +133,8 @@ namespace plib {
|
||||
}
|
||||
else if (arg.startsWith("-"))
|
||||
{
|
||||
auto p = arg.begin() + 1;
|
||||
opt = getopt_short(arg.substr(p,p + 1));
|
||||
auto p = std::next(arg.begin(), 1);
|
||||
opt = getopt_short(arg.substr(p, std::next(p, 1)));
|
||||
++p;
|
||||
if (p != arg.end())
|
||||
{
|
||||
@ -226,7 +226,7 @@ namespace plib {
|
||||
{
|
||||
line += v + "|";
|
||||
}
|
||||
line = line.left(line.begin() + (line.len() - 1));
|
||||
line = line.left(std::next(line.begin(), (line.len() - 1)));
|
||||
}
|
||||
else
|
||||
line += "Value";
|
||||
|
@ -104,7 +104,7 @@ void pstring_t<F>::pcopy(const mem_t *from, std::size_t size)
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::substr(const iterator &start, const iterator &end) const
|
||||
const pstring_t<F> pstring_t<F>::substr(const const_iterator &start, const const_iterator &end) const
|
||||
{
|
||||
pstring_t ret;
|
||||
//FIXME: throw ?
|
||||
@ -116,7 +116,7 @@ template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::ucase() const
|
||||
{
|
||||
pstring_t ret = "";
|
||||
for (auto c : *this)
|
||||
for (code_t c : *this)
|
||||
if (c >= 'a' && c <= 'z')
|
||||
ret += (c - 'a' + 'A');
|
||||
else
|
||||
@ -125,12 +125,12 @@ const pstring_t<F> pstring_t<F>::ucase() const
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::iterator pstring_t<F>::find_first_not_of(const pstring_t &no) const
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find_first_not_of(const pstring_t &no) const
|
||||
{
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
{
|
||||
bool f = true;
|
||||
for (auto const jt : no)
|
||||
for (code_t const jt : no)
|
||||
{
|
||||
if (*it == jt)
|
||||
{
|
||||
@ -145,14 +145,14 @@ typename pstring_t<F>::iterator pstring_t<F>::find_first_not_of(const pstring_t
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::iterator pstring_t<F>::find_last_not_of(const pstring_t &no) const
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find_last_not_of(const pstring_t &no) const
|
||||
{
|
||||
/* FIXME: reverse iterator */
|
||||
iterator last_found = end();
|
||||
/* FIXME: reverse const_iterator */
|
||||
const_iterator last_found = end();
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
{
|
||||
bool f = true;
|
||||
for (auto const jt : no)
|
||||
for (code_t const jt : no)
|
||||
{
|
||||
if (*it == jt)
|
||||
{
|
||||
@ -167,11 +167,11 @@ typename pstring_t<F>::iterator pstring_t<F>::find_last_not_of(const pstring_t &
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::iterator pstring_t<F>::find(const pstring_t &search, iterator start) const
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find(const pstring_t &search, const_iterator start) const
|
||||
{
|
||||
for (; start != end(); ++start)
|
||||
{
|
||||
iterator itc(start);
|
||||
const_iterator itc(start);
|
||||
auto cmp = search.begin();
|
||||
while (itc != end() && cmp != search.end() && *itc == *cmp)
|
||||
{
|
||||
@ -185,7 +185,7 @@ typename pstring_t<F>::iterator pstring_t<F>::find(const pstring_t &search, iter
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::iterator pstring_t<F>::find(const code_t search, iterator start) const
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find(const code_t search, const_iterator start) const
|
||||
{
|
||||
mem_t buf[traits::MAXCODELEN+1] = { 0 };
|
||||
traits::encode(search, buf);
|
||||
@ -205,7 +205,7 @@ pstring_t<F> pstring_t<F>::replace(const pstring_t &search, const pstring_t &rep
|
||||
{
|
||||
ret += substr(last_s, s);
|
||||
ret += replace;
|
||||
last_s = s + slen;
|
||||
last_s = std::next(s, slen);
|
||||
s = find(search, last_s);
|
||||
}
|
||||
ret += substr(last_s, end());
|
||||
@ -225,7 +225,7 @@ const pstring_t<F> pstring_t<F>::rtrim(const pstring_t &ws) const
|
||||
if (f==end())
|
||||
return pstring_t("");
|
||||
else
|
||||
return substr(begin(), f + 1);
|
||||
return substr(begin(), std::next(f, 1));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
|
@ -82,25 +82,57 @@ public:
|
||||
// assignment operators
|
||||
pstring_t &operator=(const pstring_t &string) { pcopy(string); return *this; }
|
||||
|
||||
struct iterator final : public std::iterator<std::forward_iterator_tag, mem_t>
|
||||
class const_iterator final
|
||||
{
|
||||
const mem_t * p;
|
||||
public:
|
||||
explicit constexpr iterator(const mem_t *x) noexcept : p(x) {}
|
||||
iterator(const iterator &rhs) noexcept = default;
|
||||
iterator(iterator &&rhs) noexcept { p = rhs.p; }
|
||||
iterator &operator=(const iterator &it) { p = it.p; return *this; }
|
||||
iterator& operator++() noexcept { p += traits::codelen(p); return *this; }
|
||||
iterator operator++(int) noexcept { iterator tmp(*this); operator++(); return tmp; }
|
||||
bool operator==(const iterator& rhs) noexcept { return p==rhs.p; }
|
||||
bool operator!=(const iterator& rhs) noexcept { return p!=rhs.p; }
|
||||
const code_t operator*() noexcept { return traits::code(p); }
|
||||
iterator& operator+=(size_type count) { while (count>0) { --count; ++(*this); } return *this; }
|
||||
friend iterator operator+(iterator lhs, const size_type &rhs) { return (lhs += rhs); }
|
||||
class value_type final
|
||||
{
|
||||
public:
|
||||
value_type() = delete;
|
||||
value_type(const value_type &) = delete;
|
||||
value_type(value_type &&) = delete;
|
||||
value_type &operator=(const value_type &) = delete;
|
||||
value_type &operator=(value_type &&) = delete;
|
||||
operator code_t() const noexcept { return traits::code(&m); }
|
||||
private:
|
||||
const mem_t m;
|
||||
};
|
||||
|
||||
typedef value_type const *pointer;
|
||||
typedef value_type const &reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
const_iterator() noexcept : p(nullptr) { }
|
||||
explicit constexpr const_iterator(const mem_t *x) noexcept : p(x) { }
|
||||
const_iterator(const const_iterator &rhs) noexcept = default;
|
||||
const_iterator(const_iterator &&rhs) noexcept = default;
|
||||
const_iterator &operator=(const const_iterator &rhs) noexcept = default;
|
||||
const_iterator &operator=(const_iterator &&rhs) noexcept = default;
|
||||
|
||||
const_iterator& operator++() noexcept { p += traits::codelen(p); return *this; }
|
||||
const_iterator operator++(int) noexcept { const_iterator tmp(*this); operator++(); return tmp; }
|
||||
|
||||
bool operator==(const const_iterator& rhs) const noexcept { return p == rhs.p; }
|
||||
bool operator!=(const const_iterator& rhs) const noexcept { return p != rhs.p; }
|
||||
|
||||
reference operator*() const noexcept { return *reinterpret_cast<pointer>(p); }
|
||||
pointer operator->() const noexcept { return reinterpret_cast<pointer>(p); }
|
||||
|
||||
private:
|
||||
template <typename G> friend struct pstring_t;
|
||||
const mem_t * p;
|
||||
};
|
||||
|
||||
iterator begin() const { return iterator(m_ptr->str()); }
|
||||
iterator end() const { return iterator(m_ptr->str() + blen()); }
|
||||
// no non-const const_iterator for now
|
||||
typedef const_iterator iterator;
|
||||
|
||||
iterator begin() { return iterator(m_ptr->str()); }
|
||||
iterator end() { return iterator(m_ptr->str() + blen()); }
|
||||
const_iterator begin() const { return const_iterator(m_ptr->str()); }
|
||||
const_iterator end() const { return const_iterator(m_ptr->str() + blen()); }
|
||||
const_iterator cbegin() const { return const_iterator(m_ptr->str()); }
|
||||
const_iterator cend() const { return const_iterator(m_ptr->str() + blen()); }
|
||||
|
||||
// C string conversion helpers
|
||||
const mem_t *c_str() const { return m_ptr->str(); }
|
||||
@ -141,20 +173,20 @@ public:
|
||||
pstring_t& operator+=(const code_t c) { mem_t buf[traits::MAXCODELEN+1] = { 0 }; traits::encode(c, buf); pcat(buf); return *this; }
|
||||
friend pstring_t operator+(const pstring_t &lhs, const code_t rhs) { return pstring_t(lhs) += rhs; }
|
||||
|
||||
iterator find(const pstring_t &search, iterator start) const;
|
||||
iterator find(const pstring_t &search) const { return find(search, begin()); }
|
||||
iterator find(const code_t search, iterator start) const;
|
||||
iterator find(const code_t search) const { return find(search, begin()); }
|
||||
const_iterator find(const pstring_t &search, const_iterator start) const;
|
||||
const_iterator find(const pstring_t &search) const { return find(search, begin()); }
|
||||
const_iterator find(const code_t search, const_iterator start) const;
|
||||
const_iterator find(const code_t search) const { return find(search, begin()); }
|
||||
|
||||
const pstring_t substr(const iterator &start, const iterator &end) const ;
|
||||
const pstring_t substr(const iterator &start) const { return substr(start, end()); }
|
||||
const pstring_t substr(size_type start) const { return (start >= len()) ? pstring_t("") : substr(begin() + start, end()); }
|
||||
const pstring_t substr(const const_iterator &start, const const_iterator &end) const;
|
||||
const pstring_t substr(const const_iterator &start) const { return substr(start, end()); }
|
||||
const pstring_t substr(size_type start) const { return (start >= len()) ? pstring_t("") : substr(std::next(begin(), start), end()); }
|
||||
|
||||
const pstring_t left(iterator leftof) const { return substr(begin(), leftof); }
|
||||
const pstring_t right(iterator pos) const { return substr(pos, end()); }
|
||||
const pstring_t left(const_iterator leftof) const { return substr(begin(), leftof); }
|
||||
const pstring_t right(const_iterator pos) const { return substr(pos, end()); }
|
||||
|
||||
iterator find_first_not_of(const pstring_t &no) const;
|
||||
iterator find_last_not_of(const pstring_t &no) const;
|
||||
const_iterator find_first_not_of(const pstring_t &no) const;
|
||||
const_iterator find_last_not_of(const pstring_t &no) const;
|
||||
|
||||
const pstring_t ltrim(const pstring_t &ws = pstring_t(" \t\n\r")) const;
|
||||
const pstring_t rtrim(const pstring_t &ws = pstring_t(" \t\n\r")) const;
|
||||
|
@ -52,7 +52,7 @@ namespace plib
|
||||
pstring t = str.substr(p, pn);
|
||||
if (!ignore_empty || t.len() != 0)
|
||||
ret.push_back(t);
|
||||
p = pn + onstr.len();
|
||||
p = std::next(pn, onstr.len());
|
||||
pn = str.find(onstr, p);
|
||||
}
|
||||
if (p != str.end())
|
||||
|
@ -421,7 +421,7 @@ void tool_app_t::mac_out(const pstring &s, const bool cont)
|
||||
if (cont)
|
||||
{
|
||||
unsigned adj = 0;
|
||||
for (auto x : s)
|
||||
for (auto &x : s)
|
||||
adj += (x == '\t' ? 3 : 0);
|
||||
pout("{1}\\\n", s.rpad(" ", RIGHT-1-adj));
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
|
||||
{
|
||||
if (m[1].len() != 4)
|
||||
fprintf(stderr, "error with model desc %s\n", model.c_str());
|
||||
pins = m[1].left(m[1].begin() + 3);
|
||||
pins = m[1].left(std::next(m[1].begin(), 3));
|
||||
}
|
||||
add_device("QBJT_EB", tt[0], m[0]);
|
||||
add_term(tt[1], tt[0] + "." + pins.code_at(0));
|
||||
|
Loading…
Reference in New Issue
Block a user