mirror of
https://github.com/holub/mame
synced 2025-06-10 06:47:18 +03:00
Change pstring to use std::string as storage container.
This removes all allocation code from pstring. const_iterator is consequently now based on pstring::const_iterator. Removed pstring_buffer. This was class wasn't a good idea. Vas was right: This change did not impact runtime performance. Startup performance (string intensive) increased. (nw)
This commit is contained in:
parent
ac856bc4d1
commit
ac13946ffb
@ -501,7 +501,7 @@ void netlist_mame_analog_output_t::static_set_params(device_t &device, const cha
|
||||
void netlist_mame_analog_output_t::custom_netlist_additions(netlist::setup_t &setup)
|
||||
{
|
||||
const pstring pin(m_in, pstring::UTF8);
|
||||
pstring dname = "OUT_" + pin;
|
||||
pstring dname = pstring("OUT_") + pin;
|
||||
m_delegate.bind_relative_to(owner()->machine().root_device());
|
||||
|
||||
plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(analog_callback)>(setup.netlist(), setup.build_fqn(dname));
|
||||
@ -783,7 +783,7 @@ netlist_mame_device_t::netlist_mame_device_t(const machine_config &mconfig, devi
|
||||
|
||||
netlist_mame_device_t::~netlist_mame_device_t()
|
||||
{
|
||||
pstring::resetmem();
|
||||
LOG_DEV_CALLS(("~netlist_mame_device_t\n"));
|
||||
}
|
||||
|
||||
void netlist_mame_device_t::static_set_constructor(device_t &device, void (*setup_func)(netlist::setup_t &))
|
||||
@ -795,9 +795,15 @@ void netlist_mame_device_t::static_set_constructor(device_t &device, void (*setu
|
||||
|
||||
void netlist_mame_device_t::device_config_complete()
|
||||
{
|
||||
LOG_DEV_CALLS(("device_config_complete\n"));
|
||||
LOG_DEV_CALLS(("device_config_complete %s %s\n", this->mconfig().gamedrv().name, this->tag()));
|
||||
}
|
||||
|
||||
void netlist_mame_device_t::device_validity_check(validity_checker &valid) const
|
||||
{
|
||||
LOG_DEV_CALLS(("device_validity_check %s\n", this->mconfig().gamedrv().name));
|
||||
}
|
||||
|
||||
|
||||
void netlist_mame_device_t::device_start()
|
||||
{
|
||||
LOG_DEV_CALLS(("device_start entry %s\n", tag()));
|
||||
@ -970,8 +976,6 @@ void netlist_mame_cpu_device_t::device_start()
|
||||
{
|
||||
netlist_mame_device_t::device_start();
|
||||
|
||||
LOG_DEV_CALLS(("cpu device_start %s\n", tag()));
|
||||
|
||||
// State support
|
||||
|
||||
state_add(STATE_GENPC, "GENPC", m_genPC).noshow();
|
||||
|
@ -123,6 +123,7 @@ protected:
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_config_complete() override;
|
||||
virtual void device_validity_check(validity_checker &valid) const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_stop() override;
|
||||
virtual void device_reset() override;
|
||||
|
@ -261,8 +261,6 @@ netlist_t::~netlist_t()
|
||||
{
|
||||
m_nets.clear();
|
||||
m_devices.clear();
|
||||
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
nl_double netlist_t::gmin() const
|
||||
|
@ -1349,7 +1349,6 @@ namespace netlist
|
||||
this->emplace(i, dev, pstring(names.p[i], pstring::UTF8));
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// inline implementations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -41,8 +41,6 @@ setup_t::~setup_t()
|
||||
m_param_values.clear();
|
||||
|
||||
m_sources.clear();
|
||||
|
||||
pstring::resetmem();
|
||||
}
|
||||
|
||||
pstring setup_t::build_fqn(const pstring &obj_name) const
|
||||
@ -97,10 +95,10 @@ bool setup_t::device_exists(const pstring &name) const
|
||||
void setup_t::register_model(const pstring &model_in)
|
||||
{
|
||||
auto pos = model_in.find(" ");
|
||||
if (pos == model_in.end())
|
||||
if (pos == pstring::npos)
|
||||
log().fatal(MF_1_UNABLE_TO_PARSE_MODEL_1, model_in);
|
||||
pstring model = model_in.left(pos).trim().ucase();
|
||||
pstring def = model_in.substr(std::next(pos, 1)).trim();
|
||||
pstring def = model_in.substr(pos + 1).trim();
|
||||
if (!m_models.insert({model, def}).second)
|
||||
log().fatal(MF_1_MODEL_ALREADY_EXISTS_1, model_in);
|
||||
}
|
||||
@ -791,13 +789,13 @@ static pstring model_string(detail::model_map_t &map)
|
||||
void setup_t::model_parse(const pstring &model_in, detail::model_map_t &map)
|
||||
{
|
||||
pstring model = model_in;
|
||||
pstring::iterator pos(nullptr);
|
||||
std::size_t pos = 0;
|
||||
pstring key;
|
||||
|
||||
while (true)
|
||||
{
|
||||
pos = model.find("(");
|
||||
if (pos != model.end()) break;
|
||||
if (pos != pstring::npos) break;
|
||||
|
||||
key = model.ucase();
|
||||
auto i = m_models.find(key);
|
||||
@ -818,19 +816,19 @@ 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(std::next(pos, 1)).trim();
|
||||
pstring remainder = model.substr(pos + 1).trim();
|
||||
if (!remainder.endsWith(")"))
|
||||
log().fatal(MF_1_MODEL_ERROR_1, model);
|
||||
// FIMXE: Not optimal
|
||||
remainder = remainder.left(std::next(remainder.begin(), (remainder.len() - 1)));
|
||||
remainder = remainder.left(remainder.len() - 1);
|
||||
|
||||
std::vector<pstring> pairs(plib::psplit(remainder," ", true));
|
||||
for (pstring &pe : pairs)
|
||||
{
|
||||
auto pose = pe.find("=");
|
||||
if (pose == pe.end())
|
||||
if (pose == pstring::npos)
|
||||
log().fatal(MF_1_MODEL_ERROR_ON_PAIR_1, model);
|
||||
map[pe.left(pose).ucase()] = pe.substr(std::next(pose, 1));
|
||||
map[pe.left(pose).ucase()] = pe.substr(pose + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -854,7 +852,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 = std::next(tmp.begin(), (tmp.len() - 1));
|
||||
auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.len() - 1));
|
||||
switch (*p)
|
||||
{
|
||||
case 'M': factor = 1e6; break;
|
||||
@ -870,7 +868,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(std::next(tmp.begin(), (tmp.len() - 1)));
|
||||
tmp = tmp.left(tmp.len() - 1);
|
||||
return tmp.as_double() * factor;
|
||||
}
|
||||
|
||||
@ -975,8 +973,8 @@ bool setup_t::parse_stream(plib::putf8_reader &istrm, const pstring &name)
|
||||
void setup_t::register_define(pstring defstr)
|
||||
{
|
||||
auto p = defstr.find("=");
|
||||
if (p != defstr.end())
|
||||
register_define(defstr.left(p), defstr.substr(std::next(p, 1)));
|
||||
if (p != pstring::npos)
|
||||
register_define(defstr.left(p), defstr.substr(p+1));
|
||||
else
|
||||
register_define(defstr, "1");
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ plog_dispatch_intf::~plog_dispatch_intf()
|
||||
pfmt::pfmt(const pstring &fmt)
|
||||
: m_str(m_str_buf), m_allocated(0), m_arg(0)
|
||||
{
|
||||
std::size_t l = fmt.blen() + 1;
|
||||
std::size_t l = fmt.size() + 1;
|
||||
if (l>sizeof(m_str_buf))
|
||||
{
|
||||
m_allocated = 2 * l;
|
||||
|
@ -86,7 +86,7 @@ static int get_prio(pstring v)
|
||||
{
|
||||
if (v == "(" || v == ")")
|
||||
return 1;
|
||||
else if (v.left(std::next(v.begin(),1)) >= "a" && v.left(std::next(v.begin(),1)) <= "z")
|
||||
else if (v.left(1) >= "a" && v.left(1) <= "z")
|
||||
return 0;
|
||||
else if (v == "*" || v == "/")
|
||||
return 20;
|
||||
@ -111,7 +111,7 @@ void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring
|
||||
{
|
||||
// Shunting-yard infix parsing
|
||||
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
|
||||
std::vector<pstring> sexpr(plib::psplit(expr.replace(" ",""), sep));
|
||||
std::vector<pstring> sexpr(plib::psplit(expr.replace_all(" ",""), sep));
|
||||
std::stack<pstring> opstk;
|
||||
std::vector<pstring> postfix;
|
||||
|
||||
|
@ -133,17 +133,19 @@ namespace plib {
|
||||
}
|
||||
else if (arg.startsWith("-"))
|
||||
{
|
||||
auto p = std::next(arg.begin(), 1);
|
||||
opt = getopt_short(arg.substr(p, std::next(p, 1)));
|
||||
std::size_t p = 1;
|
||||
opt = getopt_short(arg.substr(p, 1));
|
||||
++p;
|
||||
if (p != arg.end())
|
||||
if (p < arg.len())
|
||||
{
|
||||
has_equal_arg = true;
|
||||
opt_arg = arg.substr(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return i;
|
||||
}
|
||||
if (opt == nullptr)
|
||||
return i;
|
||||
if (opt->has_argument())
|
||||
@ -226,7 +228,7 @@ namespace plib {
|
||||
{
|
||||
line += v + "|";
|
||||
}
|
||||
line = line.left(std::next(line.begin(), (line.len() - 1)));
|
||||
line = line.left(line.len() - 1);
|
||||
}
|
||||
else
|
||||
line += "Value";
|
||||
|
@ -183,7 +183,7 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
{
|
||||
/* skip ws */
|
||||
pstring::code_t c = getc();
|
||||
while (m_whitespace.find(c) != m_whitespace.end())
|
||||
while (m_whitespace.find(c) != pstring::npos)
|
||||
{
|
||||
c = getc();
|
||||
if (eof())
|
||||
@ -191,7 +191,7 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
return token_t(ENDOFFILE);
|
||||
}
|
||||
}
|
||||
if (m_number_chars_start.find(c) != m_number_chars_start.end())
|
||||
if (m_number_chars_start.find(c) != pstring::npos)
|
||||
{
|
||||
/* read number while we receive number or identifier chars
|
||||
* treat it as an identifier when there are identifier chars in it
|
||||
@ -200,9 +200,9 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
token_type ret = NUMBER;
|
||||
pstring tokstr = "";
|
||||
while (true) {
|
||||
if (m_identifier_chars.find(c) != m_identifier_chars.end() && m_number_chars.find(c) == m_number_chars.end())
|
||||
if (m_identifier_chars.find(c) != pstring::npos && m_number_chars.find(c) == pstring::npos)
|
||||
ret = IDENTIFIER;
|
||||
else if (m_number_chars.find(c) == m_number_chars.end())
|
||||
else if (m_number_chars.find(c) == pstring::npos)
|
||||
break;
|
||||
tokstr += c;
|
||||
c = getc();
|
||||
@ -210,11 +210,11 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
ungetc(c);
|
||||
return token_t(ret, tokstr);
|
||||
}
|
||||
else if (m_identifier_chars.find(c) != m_identifier_chars.end())
|
||||
else if (m_identifier_chars.find(c) != pstring::npos)
|
||||
{
|
||||
/* read identifier till non identifier char */
|
||||
pstring tokstr = "";
|
||||
while (m_identifier_chars.find(c) != m_identifier_chars.end())
|
||||
while (m_identifier_chars.find(c) != pstring::npos)
|
||||
{
|
||||
tokstr += c;
|
||||
c = getc();
|
||||
@ -241,7 +241,7 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
{
|
||||
/* read identifier till first identifier char or ws */
|
||||
pstring tokstr = "";
|
||||
while ((m_identifier_chars.find(c) == m_identifier_chars.end()) && (m_whitespace.find(c) == m_whitespace.end()))
|
||||
while ((m_identifier_chars.find(c) == pstring::npos) && (m_whitespace.find(c) == pstring::npos))
|
||||
{
|
||||
tokstr += c;
|
||||
/* expensive, check for single char tokens */
|
||||
@ -385,33 +385,33 @@ ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
|
||||
pstring ppreprocessor::replace_macros(const pstring &line)
|
||||
{
|
||||
std::vector<pstring> elems(psplit(line, m_expr_sep));
|
||||
pstringbuffer ret("");
|
||||
pstring ret("");
|
||||
for (auto & elem : elems)
|
||||
{
|
||||
define_t *def = get_define(elem);
|
||||
if (def != nullptr)
|
||||
ret.cat(def->m_replace);
|
||||
ret += def->m_replace;
|
||||
else
|
||||
ret.cat(elem);
|
||||
ret += elem;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static pstring catremainder(const std::vector<pstring> &elems, std::size_t start, pstring sep)
|
||||
{
|
||||
pstringbuffer ret("");
|
||||
pstring ret("");
|
||||
for (auto & elem : elems)
|
||||
{
|
||||
ret.cat(elem);
|
||||
ret.cat(sep);
|
||||
ret += elem;
|
||||
ret += sep;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pstring ppreprocessor::process_line(const pstring &line)
|
||||
{
|
||||
pstring lt = line.replace("\t"," ").trim();
|
||||
pstringbuffer ret;
|
||||
pstring lt = line.replace_all("\t"," ").trim();
|
||||
pstring ret;
|
||||
m_lineno++;
|
||||
// FIXME ... revise and extend macro handling
|
||||
if (lt.startsWith("#"))
|
||||
@ -422,7 +422,7 @@ pstring ppreprocessor::process_line(const pstring &line)
|
||||
m_level++;
|
||||
std::size_t start = 0;
|
||||
lt = replace_macros(lt);
|
||||
std::vector<pstring> t(psplit(lt.substr(3).replace(" ",""), m_expr_sep));
|
||||
std::vector<pstring> t(psplit(lt.substr(3).replace_all(" ",""), m_expr_sep));
|
||||
int val = static_cast<int>(expr(t, start, 0));
|
||||
if (val == 0)
|
||||
m_ifflag |= (1 << m_level);
|
||||
@ -477,7 +477,7 @@ pstring ppreprocessor::process_line(const pstring &line)
|
||||
lt = replace_macros(lt);
|
||||
if (m_ifflag == 0)
|
||||
{
|
||||
ret.cat(lt);
|
||||
ret += lt;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -127,7 +127,7 @@ private:
|
||||
|
||||
int m_lineno;
|
||||
pstring m_cur_line;
|
||||
pstring::iterator m_px;
|
||||
pstring::const_iterator m_px;
|
||||
pstring::code_t m_unget;
|
||||
|
||||
/* tokenizer stuff follows ... */
|
||||
|
@ -367,7 +367,7 @@ pstream::pos_type pomemstream::vtell()
|
||||
bool putf8_reader::readline(pstring &line)
|
||||
{
|
||||
pstring::code_t c = 0;
|
||||
m_linebuf.clear();
|
||||
m_linebuf = "";
|
||||
if (!this->readcode(c))
|
||||
{
|
||||
line = "";
|
||||
|
@ -148,19 +148,19 @@ public:
|
||||
postringstream() : postream(0) { }
|
||||
virtual ~postringstream() override;
|
||||
|
||||
const pstringbuffer &str() { return m_buf; }
|
||||
const pstring &str() { return m_buf; }
|
||||
|
||||
protected:
|
||||
/* write n bytes to stream */
|
||||
virtual void vwrite(const void *buf, const pos_type n) override
|
||||
{
|
||||
m_buf.cat(buf, n);
|
||||
m_buf += pstring(static_cast<const pstring::mem_t *>(buf), n, pstring::UTF8);
|
||||
}
|
||||
virtual void vseek(const pos_type n) override { }
|
||||
virtual pos_type vtell() override { return m_buf.len(); }
|
||||
|
||||
private:
|
||||
pstringbuffer m_buf;
|
||||
pstring m_buf;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -317,17 +317,17 @@ public:
|
||||
char b[4];
|
||||
if (m_strm.read(&b[0], 1) != 1)
|
||||
return false;
|
||||
const unsigned l = pstring::traits::codelen(b);
|
||||
const unsigned l = pstring::traits_type::codelen(b);
|
||||
for (unsigned i = 1; i < l; i++)
|
||||
if (m_strm.read(&b[i], 1) != 1)
|
||||
return false;
|
||||
c = pstring::traits::code(b);
|
||||
c = pstring::traits_type::code(b);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
pistream &m_strm;
|
||||
pstringbuffer m_linebuf;
|
||||
pstring m_linebuf;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -348,7 +348,7 @@ public:
|
||||
|
||||
void write(const pstring &text) const
|
||||
{
|
||||
m_strm.write(text.c_str(), text.blen());
|
||||
m_strm.write(text.c_str(), text.size());
|
||||
}
|
||||
|
||||
void write(const pstring::code_t c) const
|
||||
@ -391,8 +391,8 @@ public:
|
||||
|
||||
void write(const pstring &s)
|
||||
{
|
||||
write(s.blen());
|
||||
m_strm.write(s.c_str(), s.blen());
|
||||
write(s.size());
|
||||
m_strm.write(s.c_str(), s.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -11,16 +11,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
#include <cstdlib>
|
||||
|
||||
template <typename F> pstr_t pstring_t<F>::m_zero(0);
|
||||
|
||||
template<typename F>
|
||||
pstring_t<F>::~pstring_t()
|
||||
{
|
||||
if (m_ptr != nullptr)
|
||||
sfree(m_ptr);
|
||||
}
|
||||
#include <atomic>
|
||||
|
||||
template <typename T>
|
||||
std::size_t strlen_mem(const T *s)
|
||||
@ -31,44 +22,15 @@ std::size_t strlen_mem(const T *s)
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::pcat(const mem_t *s)
|
||||
{
|
||||
std::size_t slen = strlen_mem(s);
|
||||
pstr_t *n = salloc(m_ptr->len() + slen);
|
||||
if (m_ptr->len() > 0)
|
||||
n->copy_from(m_ptr->str(), m_ptr->len());
|
||||
if (slen > 0)
|
||||
std::copy(s, s + slen, n->str() + m_ptr->len());
|
||||
*(n->str() + n->len()) = 0;
|
||||
sfree(m_ptr);
|
||||
m_ptr = n;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::pcat(const pstring_t &s)
|
||||
{
|
||||
std::size_t slen = s.blen();
|
||||
pstr_t *n = salloc(m_ptr->len() + slen);
|
||||
if (m_ptr->len() > 0)
|
||||
n->copy_from(m_ptr->str(), m_ptr->len());
|
||||
if (slen > 0)
|
||||
std::copy(s.c_str(), s.c_str() + slen, n->str() + m_ptr->len());
|
||||
*(n->str() + n->len()) = 0;
|
||||
sfree(m_ptr);
|
||||
m_ptr = n;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
int pstring_t<F>::pcmp(const pstring_t &right) const
|
||||
{
|
||||
std::size_t l = std::min(blen(), right.blen());
|
||||
std::size_t l = std::min(size(), right.size());
|
||||
if (l == 0)
|
||||
{
|
||||
if (blen() == 0 && right.blen() == 0)
|
||||
if (size() == 0 && right.size() == 0)
|
||||
return 0;
|
||||
else if (right.blen() == 0)
|
||||
else if (right.size() == 0)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
@ -83,40 +45,36 @@ int pstring_t<F>::pcmp(const pstring_t &right) const
|
||||
int ret = (si == this->end() ? 0 : static_cast<int>(*si) - static_cast<int>(*ri));
|
||||
if (ret == 0)
|
||||
{
|
||||
if (this->blen() > right.blen())
|
||||
if (this->size() > right.size())
|
||||
ret = 1;
|
||||
else if (this->blen() < right.blen())
|
||||
else if (this->size() < right.size())
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::pcopy(const mem_t *from, std::size_t size)
|
||||
{
|
||||
pstr_t *n = salloc(size * sizeof(mem_t));
|
||||
if (size > 0)
|
||||
n->copy_from(static_cast<const char *>(from), size);
|
||||
*(static_cast<mem_t *>(n->str()) + size) = 0;
|
||||
sfree(m_ptr);
|
||||
m_ptr = n;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::substr(const const_iterator &start, const const_iterator &end) const
|
||||
pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const
|
||||
{
|
||||
pstring_t ret;
|
||||
//FIXME: throw ?
|
||||
ret.pcopy(start.p, static_cast<std::size_t>(end.p - start.p));
|
||||
const size_type l = len();
|
||||
if (start < l)
|
||||
{
|
||||
if (nlen == npos || start + nlen > l)
|
||||
nlen = l - start;
|
||||
auto ps = std::next(begin(), static_cast<difference_type>(start));
|
||||
auto pe = std::next(ps, static_cast<difference_type>(nlen));
|
||||
ret.m_str.assign(ps.p, pe.p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::ucase() const
|
||||
pstring_t<F> pstring_t<F>::ucase() const
|
||||
{
|
||||
pstring_t ret = "";
|
||||
for (code_t c : *this)
|
||||
for (const auto &c : *this)
|
||||
if (c >= 'a' && c <= 'z')
|
||||
ret += (c - 'a' + 'A');
|
||||
else
|
||||
@ -125,9 +83,10 @@ const pstring_t<F> pstring_t<F>::ucase() const
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find_first_not_of(const pstring_t &no) const
|
||||
typename pstring_t<F>::size_type pstring_t<F>::find_first_not_of(const pstring_t &no) const
|
||||
{
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
size_type pos = 0;
|
||||
for (auto it = begin(); it != end(); ++it, ++pos)
|
||||
{
|
||||
bool f = true;
|
||||
for (code_t const jt : no)
|
||||
@ -139,17 +98,18 @@ typename pstring_t<F>::const_iterator pstring_t<F>::find_first_not_of(const pstr
|
||||
}
|
||||
}
|
||||
if (f)
|
||||
return it;
|
||||
return pos;
|
||||
}
|
||||
return end();
|
||||
return npos;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find_last_not_of(const pstring_t &no) const
|
||||
typename pstring_t<F>::size_type pstring_t<F>::find_last_not_of(const pstring_t &no) const
|
||||
{
|
||||
/* FIXME: reverse const_iterator */
|
||||
const_iterator last_found = end();
|
||||
for (auto it = begin(); it != end(); ++it)
|
||||
/* FIXME: reverse iterator */
|
||||
size_type last_found = npos;
|
||||
size_type pos = 0;
|
||||
for (auto it = begin(); it != end(); ++it, ++pos)
|
||||
{
|
||||
bool f = true;
|
||||
for (code_t const jt : no)
|
||||
@ -161,17 +121,18 @@ typename pstring_t<F>::const_iterator pstring_t<F>::find_last_not_of(const pstri
|
||||
}
|
||||
}
|
||||
if (f)
|
||||
last_found = it;
|
||||
last_found = pos;
|
||||
}
|
||||
return last_found;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find(const pstring_t &search, const_iterator start) const
|
||||
typename pstring_t<F>::size_type pstring_t<F>::find(const pstring_t &search, size_type start) const
|
||||
{
|
||||
for (; start != end(); ++start)
|
||||
auto istart = std::next(begin(), static_cast<difference_type>(start));
|
||||
for (; istart != end(); ++istart)
|
||||
{
|
||||
const_iterator itc(start);
|
||||
auto itc(istart);
|
||||
auto cmp = search.begin();
|
||||
while (itc != end() && cmp != search.end() && *itc == *cmp)
|
||||
{
|
||||
@ -180,56 +141,41 @@ typename pstring_t<F>::const_iterator pstring_t<F>::find(const pstring_t &search
|
||||
}
|
||||
if (cmp == search.end())
|
||||
return start;
|
||||
++start;
|
||||
}
|
||||
return end();
|
||||
return npos;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
typename pstring_t<F>::const_iterator pstring_t<F>::find(const code_t search, const_iterator start) const
|
||||
typename pstring_t<F>::size_type pstring_t<F>::find(code_t search, size_type start) const
|
||||
{
|
||||
mem_t buf[traits::MAXCODELEN+1] = { 0 };
|
||||
traits::encode(search, buf);
|
||||
mem_t buf[traits_type::MAXCODELEN+1] = { 0 };
|
||||
traits_type::encode(search, buf);
|
||||
return find(pstring_t(&buf[0], UTF8), start);
|
||||
}
|
||||
|
||||
|
||||
template<typename F>
|
||||
pstring_t<F> pstring_t<F>::replace(const pstring_t &search, const pstring_t &replace) const
|
||||
pstring_t<F> pstring_t<F>::replace_all(const pstring_t &search, const pstring_t &replace) const
|
||||
{
|
||||
pstring_t ret("");
|
||||
const size_type slen = search.len();
|
||||
|
||||
auto last_s = begin();
|
||||
auto s = find(search, last_s);
|
||||
while (s != end())
|
||||
size_type last_s = 0;
|
||||
size_type s = find(search, last_s);
|
||||
while (s != npos)
|
||||
{
|
||||
ret += substr(last_s, s);
|
||||
ret += substr(last_s, s - last_s);
|
||||
ret += replace;
|
||||
last_s = std::next(s, slen);
|
||||
last_s = s + slen;
|
||||
s = find(search, last_s);
|
||||
}
|
||||
ret += substr(last_s, end());
|
||||
ret += substr(last_s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::ltrim(const pstring_t &ws) const
|
||||
{
|
||||
return substr(find_first_not_of(ws), end());
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::rtrim(const pstring_t &ws) const
|
||||
{
|
||||
auto f = find_last_not_of(ws);
|
||||
if (f==end())
|
||||
return pstring_t("");
|
||||
else
|
||||
return substr(begin(), std::next(f, 1));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const size_type cnt) const
|
||||
pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const size_type cnt) const
|
||||
{
|
||||
// FIXME: pstringbuffer ret(*this);
|
||||
|
||||
@ -240,23 +186,16 @@ const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const size_type cnt)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::pcopy(const mem_t *from)
|
||||
{
|
||||
pcopy(from, strlen_mem(from));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
double pstring_t<F>::as_double(bool *error) const
|
||||
{
|
||||
double ret;
|
||||
char *e = nullptr;
|
||||
std::size_t e = 0;
|
||||
|
||||
if (error != nullptr)
|
||||
*error = false;
|
||||
ret = std::strtod(c_str(), &e);
|
||||
if (*e != 0)
|
||||
ret = std::stod(m_str, &e);
|
||||
if (e != size())
|
||||
if (error != nullptr)
|
||||
*error = true;
|
||||
return ret;
|
||||
@ -266,248 +205,20 @@ template<typename F>
|
||||
long pstring_t<F>::as_long(bool *error) const
|
||||
{
|
||||
long ret;
|
||||
char *e = nullptr;
|
||||
std::size_t e = 0;
|
||||
|
||||
if (error != nullptr)
|
||||
*error = false;
|
||||
if (startsWith("0x"))
|
||||
ret = std::strtol(substr(2).c_str(), &e, 16);
|
||||
ret = std::stol(substr(2).m_str, &e, 16);
|
||||
else
|
||||
ret = std::strtol(c_str(), &e, 10);
|
||||
if (*e != 0)
|
||||
ret = std::stol(m_str, &e, 10);
|
||||
if (e != size())
|
||||
if (error != nullptr)
|
||||
*error = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
bool pstring_t<F>::startsWith(const pstring_t &arg) const
|
||||
{
|
||||
if (arg.blen() > blen())
|
||||
return false;
|
||||
else
|
||||
return std::equal(arg.c_str(), arg.c_str() + arg.blen(), c_str());
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
bool pstring_t<F>::endsWith(const pstring_t &arg) const
|
||||
{
|
||||
if (arg.blen() > blen())
|
||||
return false;
|
||||
else
|
||||
return std::equal(arg.c_str(), arg.c_str() + arg.blen(), c_str()+this->blen()-arg.blen());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// pstringbuffer
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
pstringbuffer::~pstringbuffer()
|
||||
{
|
||||
if (m_ptr != nullptr)
|
||||
plib::pfree_array(m_ptr);
|
||||
}
|
||||
|
||||
void pstringbuffer::resize(const std::size_t size)
|
||||
{
|
||||
if (m_ptr == nullptr)
|
||||
{
|
||||
m_size = DEFAULT_SIZE;
|
||||
while (m_size <= size)
|
||||
m_size *= 2;
|
||||
m_ptr = plib::palloc_array<char>(m_size);
|
||||
*m_ptr = 0;
|
||||
m_len = 0;
|
||||
}
|
||||
else if (m_size < size)
|
||||
{
|
||||
while (m_size < size)
|
||||
m_size *= 2;
|
||||
char *new_buf = plib::palloc_array<char>(m_size);
|
||||
std::copy(m_ptr, m_ptr + m_len + 1, new_buf);
|
||||
plib::pfree_array(m_ptr);
|
||||
m_ptr = new_buf;
|
||||
}
|
||||
}
|
||||
|
||||
void pstringbuffer::pcopy(const char *from)
|
||||
{
|
||||
std::size_t nl = strlen_mem(from) + 1;
|
||||
resize(nl);
|
||||
std::copy(from, from + nl, m_ptr);
|
||||
}
|
||||
|
||||
void pstringbuffer::pcopy(const pstring &from)
|
||||
{
|
||||
std::size_t nl = from.blen() + 1;
|
||||
resize(nl);
|
||||
std::copy(from.c_str(), from.c_str() + nl, m_ptr);
|
||||
}
|
||||
|
||||
void pstringbuffer::pcat(const char *s)
|
||||
{
|
||||
const std::size_t slen = strlen_mem(s);
|
||||
const std::size_t nl = m_len + slen + 1;
|
||||
resize(nl);
|
||||
std::copy(s, s + slen + 1, m_ptr + m_len);
|
||||
m_len += slen;
|
||||
}
|
||||
|
||||
void pstringbuffer::pcat(const void *m, std::size_t l)
|
||||
{
|
||||
const std::size_t nl = m_len + l + 1;
|
||||
resize(nl);
|
||||
std::copy(static_cast<const char *>(m), static_cast<const char *>(m) + l, m_ptr + m_len);
|
||||
m_len += l;
|
||||
*(m_ptr + m_len) = 0;
|
||||
}
|
||||
|
||||
void pstringbuffer::pcat(const pstring &s)
|
||||
{
|
||||
const std::size_t slen = s.blen();
|
||||
const std::size_t nl = m_len + slen + 1;
|
||||
resize(nl);
|
||||
std::copy(s.c_str(), s.c_str() + slen, m_ptr + m_len);
|
||||
m_len += slen;
|
||||
m_ptr[m_len] = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// static stuff ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Cached allocation of string memory
|
||||
*
|
||||
* This improves startup performance by 30%.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
|
||||
static std::stack<pstr_t *> *stk = nullptr;
|
||||
|
||||
static inline std::size_t countleadbits(std::size_t x)
|
||||
{
|
||||
#ifndef count_leading_zeros
|
||||
std::size_t msk;
|
||||
std::size_t ret;
|
||||
if (x < 0x100)
|
||||
{
|
||||
msk = 0x80;
|
||||
ret = 24;
|
||||
}
|
||||
else if (x < 0x10000)
|
||||
{
|
||||
msk = 0x8000;
|
||||
ret = 16;
|
||||
}
|
||||
else if (x < 0x1000000)
|
||||
{
|
||||
msk = 0x800000;
|
||||
ret = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
msk = 0x80000000;
|
||||
ret = 0;
|
||||
}
|
||||
while ((msk & x) == 0 && ret < 31)
|
||||
{
|
||||
msk = msk >> 1;
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return count_leading_zeros(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::sfree(pstr_t *s)
|
||||
{
|
||||
if (s != nullptr)
|
||||
{
|
||||
bool b = s->dec_and_check();
|
||||
if ( b && s != &m_zero)
|
||||
{
|
||||
if (stk != nullptr)
|
||||
{
|
||||
size_type sn= ((32 - countleadbits(s->len())) + 1) / 2;
|
||||
stk[sn].push(s);
|
||||
}
|
||||
else
|
||||
plib::pfree_array(reinterpret_cast<char *>(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
pstr_t *pstring_t<F>::salloc(std::size_t n)
|
||||
{
|
||||
if (stk == nullptr)
|
||||
stk = plib::palloc_array<std::stack<pstr_t *>>(17);
|
||||
pstr_t *p;
|
||||
std::size_t sn= ((32 - countleadbits(n)) + 1) / 2;
|
||||
std::size_t size = sizeof(pstr_t) + (static_cast<std::size_t>(1)<<(sn * 2)) + 1;
|
||||
if (stk[sn].empty())
|
||||
p = reinterpret_cast<pstr_t *>(plib::palloc_array<char>(size));
|
||||
else
|
||||
{
|
||||
p = stk[sn].top();
|
||||
stk[sn].pop();
|
||||
}
|
||||
|
||||
// str_t *p = (str_t *) mm_malloc(size, 8);
|
||||
p->init(n);
|
||||
return p;
|
||||
}
|
||||
template<typename F>
|
||||
void pstring_t<F>::resetmem()
|
||||
{
|
||||
if (stk != nullptr)
|
||||
{
|
||||
for (std::size_t i=0; i<=16; i++)
|
||||
{
|
||||
for (; stk[i].size() > 0; )
|
||||
{
|
||||
plib::pfree_array(stk[i].top());
|
||||
stk[i].pop();
|
||||
}
|
||||
}
|
||||
plib::pfree_array(stk);
|
||||
stk = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
template<typename F>
|
||||
void pstring_t<F>::sfree(pstr_t *s)
|
||||
{
|
||||
bool b = s->dec_and_check();
|
||||
if ( b && s != &m_zero)
|
||||
{
|
||||
plib::pfree_array(((char *)s));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
pstr_t *pstring_t<F>::salloc(std::size_t n)
|
||||
{
|
||||
int size = sizeof(pstr_t) + n + 1;
|
||||
pstr_t *p = (pstr_t *) plib::palloc_array<char>(size);
|
||||
// str_t *p = (str_t *) mm_malloc(size, 8);
|
||||
p->init(n);
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void pstring_t<F>::resetmem()
|
||||
{
|
||||
// Release the 0 string
|
||||
}
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// template stuff ...
|
||||
// ----------------------------------------------------------------------------------------
|
||||
@ -517,4 +228,3 @@ template struct pstring_t<putf8_traits>;
|
||||
|
||||
const unsigned pu8_traits::MAXCODELEN;
|
||||
const unsigned putf8_traits::MAXCODELEN;
|
||||
const int pstringbuffer::DEFAULT_SIZE;
|
||||
|
@ -9,44 +9,25 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// pstring: immutable strings ...
|
||||
// pstring: semi-immutable strings ...
|
||||
//
|
||||
// pstrings are just a pointer to a "pascal-style" string representation.
|
||||
// It uses reference counts and only uses new memory when a string changes.
|
||||
// The only reason this class exists is the absence of support for multi-byte
|
||||
// strings in std:: which I would consider usuable for the use-cases I encounter.
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
struct pstr_t
|
||||
{
|
||||
explicit pstr_t(const std::size_t alen) { init(alen); }
|
||||
void init(const std::size_t alen)
|
||||
{
|
||||
m_ref_count = 1;
|
||||
m_len = alen;
|
||||
m_str[0] = 0;
|
||||
}
|
||||
char *str() { return &m_str[0]; }
|
||||
unsigned char *ustr() { return reinterpret_cast<unsigned char *>(&m_str[0]); }
|
||||
std::size_t len() const { return m_len; }
|
||||
void inc() { m_ref_count++; }
|
||||
bool dec_and_check() { --m_ref_count; return m_ref_count == 0; }
|
||||
void copy_from(const char *p, std::size_t n) { std::copy(p, p + n, str()); }
|
||||
private:
|
||||
int m_ref_count;
|
||||
std::size_t m_len;
|
||||
char m_str[1];
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct pstring_t
|
||||
{
|
||||
public:
|
||||
typedef F traits;
|
||||
typedef F traits_type;
|
||||
|
||||
typedef typename F::mem_t mem_t;
|
||||
typedef typename F::code_t code_t;
|
||||
typedef typename traits_type::mem_t mem_t;
|
||||
typedef typename traits_type::code_t code_t;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
enum enc_t
|
||||
{
|
||||
@ -54,33 +35,52 @@ public:
|
||||
};
|
||||
|
||||
// simple construction/destruction
|
||||
pstring_t() : m_ptr(&m_zero)
|
||||
pstring_t()
|
||||
: m_str("")
|
||||
{
|
||||
}
|
||||
~pstring_t()
|
||||
{
|
||||
init(nullptr);
|
||||
}
|
||||
~pstring_t();
|
||||
|
||||
// FIXME: Do something with encoding
|
||||
pstring_t(const mem_t *string, const enc_t enc) : m_ptr(&m_zero)
|
||||
pstring_t(const mem_t *string, const enc_t enc)
|
||||
: m_str(string)
|
||||
{
|
||||
}
|
||||
|
||||
pstring_t(const mem_t *string, const size_type len, const enc_t enc)
|
||||
: m_str(string, len)
|
||||
{
|
||||
init(string);
|
||||
}
|
||||
|
||||
template<typename C, std::size_t N>
|
||||
pstring_t(C (&string)[N]) : m_ptr(&m_zero) {
|
||||
pstring_t(C (&string)[N])
|
||||
{
|
||||
static_assert(std::is_same<C, const mem_t>::value, "pstring constructor only accepts const mem_t");
|
||||
static_assert(N>0,"pstring from array of length 0");
|
||||
static_assert(N > 0,"pstring from array of length 0");
|
||||
if (string[N-1] != 0)
|
||||
throw std::exception();
|
||||
init(string);
|
||||
m_str.assign(string, N - 1);
|
||||
}
|
||||
|
||||
pstring_t(const pstring_t &string) : m_ptr(&m_zero) { init(string); }
|
||||
pstring_t(pstring_t &&string) : m_ptr(string.m_ptr) { string.m_ptr = nullptr; }
|
||||
explicit pstring_t(code_t code) : m_ptr(&m_zero) { pstring_t t; t+= code; init(t); }
|
||||
pstring_t(const pstring_t &string)
|
||||
: m_str(string.m_str)
|
||||
{ }
|
||||
|
||||
pstring_t(pstring_t &&string)
|
||||
: m_str(string.m_str)
|
||||
{ }
|
||||
|
||||
explicit pstring_t(code_t code)
|
||||
{
|
||||
pstring_t t;
|
||||
t+= code;
|
||||
m_str.assign(t.m_str);
|
||||
}
|
||||
|
||||
// assignment operators
|
||||
pstring_t &operator=(const pstring_t &string) { pcopy(string); return *this; }
|
||||
pstring_t &operator=(const pstring_t &string) { m_str = string.m_str; return *this; }
|
||||
|
||||
class const_iterator final
|
||||
{
|
||||
@ -93,7 +93,7 @@ public:
|
||||
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); }
|
||||
operator code_t() const noexcept { return traits_type::code(&m); }
|
||||
private:
|
||||
const mem_t m;
|
||||
};
|
||||
@ -103,43 +103,55 @@ public:
|
||||
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() noexcept : p() { }
|
||||
explicit constexpr const_iterator(const std::string::const_iterator &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++() noexcept { p += traits_type::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); }
|
||||
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;
|
||||
std::string::const_iterator p;
|
||||
};
|
||||
|
||||
// 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()); }
|
||||
iterator begin() { return iterator(m_str.begin()); }
|
||||
iterator end() { return iterator(m_str.end()); }
|
||||
const_iterator begin() const { return const_iterator(m_str.begin()); }
|
||||
const_iterator end() const { return const_iterator(m_str.end()); }
|
||||
const_iterator cbegin() const { return const_iterator(m_str.begin()); }
|
||||
const_iterator cend() const { return const_iterator(m_str.end()); }
|
||||
|
||||
// C string conversion helpers
|
||||
const mem_t *c_str() const { return m_ptr->str(); }
|
||||
const mem_t *c_str() const { return static_cast<const mem_t *>(m_str.c_str()); }
|
||||
|
||||
size_type size() const { return m_str.size(); }
|
||||
|
||||
pstring_t substr(size_type start, size_type nlen = npos) const;
|
||||
|
||||
size_type find(const pstring_t &search, size_type start = 0) const;
|
||||
size_type find(code_t search, size_type start = 0) const;
|
||||
|
||||
size_type find_first_not_of(const pstring_t &no) const;
|
||||
size_type find_last_not_of(const pstring_t &no) const;
|
||||
|
||||
// concatenation operators
|
||||
pstring_t& operator+=(const pstring_t &string) { pcat(string); return *this; }
|
||||
pstring_t& operator+=(const pstring_t &string) { m_str.append(string.m_str); return *this; }
|
||||
pstring_t& operator+=(const code_t c) { mem_t buf[traits_type::MAXCODELEN+1] = { 0 }; traits_type::encode(c, buf); m_str.append(buf); return *this; }
|
||||
friend pstring_t operator+(const pstring_t &lhs, const pstring_t &rhs) { return pstring_t(lhs) += rhs; }
|
||||
friend pstring_t operator+(const pstring_t &lhs, const code_t rhs) { return pstring_t(lhs) += rhs; }
|
||||
|
||||
// comparison operators
|
||||
bool operator==(const pstring_t &string) const { return (pcmp(string) == 0); }
|
||||
@ -150,90 +162,62 @@ public:
|
||||
bool operator>(const pstring_t &string) const { return (pcmp(string) > 0); }
|
||||
bool operator>=(const pstring_t &string) const { return (pcmp(string) >= 0); }
|
||||
|
||||
/* The following is not compatible to std::string */
|
||||
|
||||
bool equals(const pstring_t &string) const { return (pcmp(string) == 0); }
|
||||
bool startsWith(const pstring_t &arg) const;
|
||||
bool endsWith(const pstring_t &arg) const;
|
||||
|
||||
pstring_t replace(const pstring_t &search, const pstring_t &replace) const;
|
||||
const pstring_t cat(const pstring_t &s) const { return *this + s; }
|
||||
const pstring_t cat(const code_t c) const { return *this + c; }
|
||||
bool startsWith(const pstring_t &arg) const { return arg.size() > size() ? false : m_str.compare(0, arg.size(), arg.m_str) == 0; }
|
||||
bool endsWith(const pstring_t &arg) const { return arg.size() > size() ? false : m_str.compare(size()-arg.size(), arg.size(), arg.m_str) == 0; }
|
||||
|
||||
size_type blen() const { return m_ptr->len(); }
|
||||
pstring_t replace_all(const pstring_t &search, const pstring_t &replace) const;
|
||||
pstring_t cat(const pstring_t &s) const { return *this + s; }
|
||||
pstring_t cat(code_t c) const { return *this + c; }
|
||||
|
||||
// conversions
|
||||
|
||||
double as_double(bool *error = nullptr) const;
|
||||
long as_long(bool *error = nullptr) const;
|
||||
|
||||
size_type len() const
|
||||
size_type len() const { return traits_type::len(m_str); }
|
||||
|
||||
/* the following are extensions to <string> */
|
||||
|
||||
pstring_t left(size_type len) const { return substr(0, len); }
|
||||
pstring_t right(size_type nlen) const
|
||||
{
|
||||
return traits::len(m_ptr);
|
||||
return nlen >= len() ? pstring_t(*this) : substr(len() - nlen, nlen);
|
||||
}
|
||||
|
||||
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; }
|
||||
pstring_t ltrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
|
||||
{
|
||||
return substr(find_first_not_of(ws));
|
||||
}
|
||||
|
||||
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()); }
|
||||
pstring_t rtrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
|
||||
{
|
||||
auto f = find_last_not_of(ws);
|
||||
if (f==npos)
|
||||
return pstring_t("");
|
||||
else
|
||||
return substr(0, f + 1);
|
||||
}
|
||||
|
||||
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()); }
|
||||
pstring_t trim(const pstring_t &ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
|
||||
|
||||
const pstring_t left(const_iterator leftof) const { return substr(begin(), leftof); }
|
||||
const pstring_t right(const_iterator pos) const { return substr(pos, end()); }
|
||||
pstring_t rpad(const pstring_t &ws, const size_type cnt) const;
|
||||
|
||||
const_iterator find_first_not_of(const pstring_t &no) const;
|
||||
const_iterator find_last_not_of(const pstring_t &no) const;
|
||||
code_t code_at(const size_type pos) const {return F::code(F::nthcode(m_str.c_str(),pos)); }
|
||||
|
||||
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;
|
||||
const pstring_t trim(const pstring_t &ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
|
||||
pstring_t ucase() const;
|
||||
|
||||
const pstring_t rpad(const pstring_t &ws, const size_type cnt) const;
|
||||
|
||||
code_t code_at(const size_type pos) const { return F::code(F::nthcode(m_ptr->str(),pos)); }
|
||||
|
||||
const pstring_t ucase() const;
|
||||
|
||||
static void resetmem();
|
||||
static const size_type npos = static_cast<size_type>(-1);
|
||||
|
||||
protected:
|
||||
pstr_t *m_ptr;
|
||||
std::string m_str;
|
||||
|
||||
private:
|
||||
void init(const mem_t *string)
|
||||
{
|
||||
m_ptr->inc();
|
||||
if (string != nullptr && *string != 0)
|
||||
pcopy(string);
|
||||
}
|
||||
void init(const pstring_t &string)
|
||||
{
|
||||
m_ptr->inc();
|
||||
pcopy(string);
|
||||
}
|
||||
|
||||
int pcmp(const pstring_t &right) const;
|
||||
|
||||
void pcopy(const mem_t *from, std::size_t size);
|
||||
|
||||
void pcopy(const mem_t *from);
|
||||
void pcopy(const pstring_t &from)
|
||||
{
|
||||
sfree(m_ptr);
|
||||
m_ptr = from.m_ptr;
|
||||
m_ptr->inc();
|
||||
}
|
||||
void pcat(const mem_t *s);
|
||||
void pcat(const pstring_t &s);
|
||||
|
||||
static pstr_t *salloc(std::size_t n);
|
||||
static void sfree(pstr_t *s);
|
||||
|
||||
static pstr_t m_zero;
|
||||
};
|
||||
|
||||
struct pu8_traits
|
||||
@ -241,7 +225,7 @@ struct pu8_traits
|
||||
static const unsigned MAXCODELEN = 1; /* in memory units */
|
||||
typedef char mem_t;
|
||||
typedef char code_t;
|
||||
static std::size_t len(const pstr_t *p) { return p->len(); }
|
||||
static std::size_t len(const std::string &p) { return p.size(); }
|
||||
static unsigned codelen(const mem_t *p) { return 1; }
|
||||
static unsigned codelen(const code_t c) { return 1; }
|
||||
static code_t code(const mem_t *p) { return *p; }
|
||||
@ -255,15 +239,13 @@ struct putf8_traits
|
||||
static const unsigned MAXCODELEN = 4; /* in memory units, RFC 3629 */
|
||||
typedef char mem_t;
|
||||
typedef unsigned code_t;
|
||||
static std::size_t len(pstr_t *p)
|
||||
static std::size_t len(const std::string &p)
|
||||
{
|
||||
std::size_t ret = 0;
|
||||
unsigned char *c = p->ustr();
|
||||
while (*c)
|
||||
for (const auto &c : p)
|
||||
{
|
||||
if (!((*c & 0xC0) == 0x80))
|
||||
if (!((c & 0xC0) == 0x80))
|
||||
ret++;
|
||||
c++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -349,80 +331,6 @@ extern template struct pstring_t<putf8_traits>;
|
||||
|
||||
typedef pstring_t<putf8_traits> pstring;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// pstringbuffer: a string buffer implementation
|
||||
//
|
||||
// string buffer are optimized to handle concatenations. This implementation is designed
|
||||
// to specifically interact with pstrings nicely.
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
struct pstringbuffer
|
||||
{
|
||||
public:
|
||||
|
||||
static const int DEFAULT_SIZE = 2048;
|
||||
// simple construction/destruction
|
||||
pstringbuffer()
|
||||
{
|
||||
init();
|
||||
resize(DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
~pstringbuffer();
|
||||
|
||||
// construction with copy
|
||||
explicit pstringbuffer(const char *string) {init(); if (string != nullptr) pcopy(string); }
|
||||
explicit pstringbuffer(const pstring &string) {init(); pcopy(string); }
|
||||
pstringbuffer(const pstringbuffer &stringb) {init(); pcopy(stringb); }
|
||||
pstringbuffer(pstringbuffer &&b) : m_ptr(b.m_ptr), m_size(b.m_size), m_len(b.m_len) { b.m_ptr = nullptr; b.m_size = 0; b.m_len = 0; }
|
||||
|
||||
// assignment operators
|
||||
pstringbuffer &operator=(const char *string) { pcopy(string); return *this; }
|
||||
pstringbuffer &operator=(const pstring &string) { pcopy(string); return *this; }
|
||||
pstringbuffer &operator=(const pstringbuffer &string) { pcopy(string); return *this; }
|
||||
|
||||
// C string conversion helpers
|
||||
const char *c_str() const { return m_ptr; }
|
||||
|
||||
// FIXME: encoding should be parameter
|
||||
operator pstring() const { return pstring(m_ptr, pstring::UTF8); }
|
||||
|
||||
// concatenation operators
|
||||
pstringbuffer& operator+=(const char c) { char buf[2] = { c, 0 }; pcat(buf); return *this; }
|
||||
pstringbuffer& operator+=(const pstring &string) { pcat(string); return *this; }
|
||||
pstringbuffer& operator+=(const char *string) { pcat(string); return *this; }
|
||||
|
||||
std::size_t len() const { return m_len; }
|
||||
|
||||
void cat(const pstring &s) { pcat(s); }
|
||||
void cat(const char *s) { pcat(s); }
|
||||
void cat(const void *m, std::size_t l) { pcat(m, l); }
|
||||
|
||||
void clear() { m_len = 0; *m_ptr = 0; }
|
||||
|
||||
private:
|
||||
|
||||
void init()
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
m_size = 0;
|
||||
m_len = 0;
|
||||
}
|
||||
|
||||
void resize(const std::size_t size);
|
||||
|
||||
void pcopy(const char *from);
|
||||
void pcopy(const pstring &from);
|
||||
void pcat(const char *s);
|
||||
void pcat(const pstring &s);
|
||||
void pcat(const void *m, std::size_t l);
|
||||
|
||||
char *m_ptr;
|
||||
std::size_t m_size;
|
||||
std::size_t m_len;
|
||||
|
||||
};
|
||||
|
||||
// custom specialization of std::hash can be injected in namespace std
|
||||
namespace std
|
||||
{
|
||||
|
@ -44,20 +44,20 @@ namespace plib
|
||||
{
|
||||
std::vector<pstring> ret;
|
||||
|
||||
pstring::iterator p = str.begin();
|
||||
pstring::iterator pn = str.find(onstr, p);
|
||||
pstring::size_type p = 0;
|
||||
pstring::size_type pn = str.find(onstr, p);
|
||||
|
||||
while (pn != str.end())
|
||||
while (pn != pstring::npos)
|
||||
{
|
||||
pstring t = str.substr(p, pn);
|
||||
pstring t = str.substr(p, pn - p);
|
||||
if (!ignore_empty || t.len() != 0)
|
||||
ret.push_back(t);
|
||||
p = std::next(pn, onstr.len());
|
||||
p = pn + onstr.len();
|
||||
pn = str.find(onstr, p);
|
||||
}
|
||||
if (p != str.end())
|
||||
if (p < str.len())
|
||||
{
|
||||
pstring t = str.substr(p, str.end());
|
||||
pstring t = str.substr(p);
|
||||
if (!ignore_empty || t.len() != 0)
|
||||
ret.push_back(t);
|
||||
}
|
||||
@ -69,13 +69,13 @@ namespace plib
|
||||
pstring col = "";
|
||||
std::vector<pstring> ret;
|
||||
|
||||
unsigned i = 0;
|
||||
while (i<str.blen())
|
||||
auto i = str.begin();
|
||||
while (i != str.end())
|
||||
{
|
||||
std::size_t p = static_cast<std::size_t>(-1);
|
||||
for (std::size_t j=0; j < onstrl.size(); j++)
|
||||
{
|
||||
if (std::equal(onstrl[j].c_str(), onstrl[j].c_str() + onstrl[j].blen(), &(str.c_str()[i])))
|
||||
if (std::equal(onstrl[j].c_str(), onstrl[j].c_str() + onstrl[j].size(), i))
|
||||
{
|
||||
p = j;
|
||||
break;
|
||||
@ -88,13 +88,13 @@ namespace plib
|
||||
|
||||
col = "";
|
||||
ret.push_back(onstrl[p]);
|
||||
i += onstrl[p].blen();
|
||||
i = std::next(i, static_cast<pstring::difference_type>(onstrl[p].len()));
|
||||
}
|
||||
else
|
||||
{
|
||||
pstring::traits::code_t c = pstring::traits::code(str.c_str() + i);
|
||||
pstring::code_t c = *i;
|
||||
col += c;
|
||||
i+=pstring::traits::codelen(c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (col != "")
|
||||
|
@ -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 (const auto &x : s)
|
||||
adj += (x == '\t' ? 3 : 0);
|
||||
pout("{1}\\\n", s.rpad(" ", RIGHT-1-adj));
|
||||
}
|
||||
@ -434,13 +434,13 @@ void tool_app_t::cmac(const netlist::factory::element_t *e)
|
||||
auto v = plib::psplit(e->param_desc(), ",");
|
||||
pstring vs;
|
||||
for (auto s : v)
|
||||
vs += ", p" + s.replace("+","").replace(".","_");
|
||||
vs += ", p" + s.replace_all("+", "").replace_all(".", "_");
|
||||
mac_out("#define " + e->name() + "(name" + vs + ")");
|
||||
mac_out("\tNET_REGISTER_DEV(" + e->name() +", name)");
|
||||
|
||||
for (auto s : v)
|
||||
{
|
||||
pstring r(s.replace("+","").replace(".","_"));
|
||||
pstring r(s.replace_all("+", "").replace_all(".", "_"));
|
||||
if (s.startsWith("+"))
|
||||
mac_out("\tNET_CONNECT(name, " + r + ", p" + r + ")");
|
||||
else
|
||||
@ -455,7 +455,7 @@ void tool_app_t::mac(const netlist::factory::element_t *e)
|
||||
pstring vs;
|
||||
for (auto s : v)
|
||||
{
|
||||
vs += ", " + s.replace("+","").replace(".","_");
|
||||
vs += ", " + s.replace_all("+", "").replace_all(".", "_");
|
||||
}
|
||||
pout("{1}(name{2})\n", e->name(), vs);
|
||||
if (v.size() > 0)
|
||||
@ -463,7 +463,7 @@ void tool_app_t::mac(const netlist::factory::element_t *e)
|
||||
pout("/*\n");
|
||||
for (auto s : v)
|
||||
{
|
||||
pstring r(s.replace("+","").replace(".","_"));
|
||||
pstring r(s.replace_all("+", "").replace_all(".", "_"));
|
||||
if (s.startsWith("+"))
|
||||
pout("{1:10}: Terminal\n",r);
|
||||
else
|
||||
@ -507,7 +507,7 @@ void tool_app_t::create_header()
|
||||
{
|
||||
last_source = e->sourcefile();
|
||||
pout("{1}\n", pstring("// ").rpad("-", 72));
|
||||
pout("{1}\n", pstring("// Source: ").cat(e->sourcefile().replace("../","")));
|
||||
pout("{1}{2}\n", pstring("// Source: "), e->sourcefile().replace_all("../", ""));
|
||||
pout("{1}\n", pstring("// ").rpad("-", 72));
|
||||
}
|
||||
cmac(e.get());
|
||||
@ -603,7 +603,7 @@ void tool_app_t::listdevices()
|
||||
if (t.second->name().startsWith(d->name()))
|
||||
{
|
||||
pstring tn(t.second->name().substr(d->name().len()+1));
|
||||
if (tn.find(".") == tn.end())
|
||||
if (tn.find(".") == pstring::npos)
|
||||
terms.push_back(tn);
|
||||
}
|
||||
}
|
||||
@ -614,7 +614,7 @@ void tool_app_t::listdevices()
|
||||
{
|
||||
pstring tn(t.first.substr(d->name().len()+1));
|
||||
//printf("\t%s %s %s\n", t.first.c_str(), t.second.c_str(), tn.c_str());
|
||||
if (tn.find(".") == tn.end())
|
||||
if (tn.find(".") == pstring::npos)
|
||||
{
|
||||
terms.push_back(tn);
|
||||
pstring resolved = nt.setup().resolve_alias(t.first);
|
||||
@ -770,8 +770,6 @@ int tool_app_t::execute()
|
||||
{
|
||||
perr("plib exception caught: {}\n", e.text());
|
||||
}
|
||||
|
||||
pstring::resetmem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,8 @@ void matrix_solver_t::setup_base(analog_net_t::list_t &nets)
|
||||
|
||||
if (net_proxy_output == nullptr)
|
||||
{
|
||||
auto net_proxy_output_u = plib::make_unique<proxied_analog_output_t>(*this, this->name() + "." + plib::pfmt("m{1}")(m_inps.size()));
|
||||
pstring nname = this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()));
|
||||
auto net_proxy_output_u = plib::make_unique<proxied_analog_output_t>(*this, nname);
|
||||
net_proxy_output = net_proxy_output_u.get();
|
||||
m_inps.push_back(std::move(net_proxy_output_u));
|
||||
nl_assert(p->net().is_analog());
|
||||
|
@ -209,8 +209,8 @@ double nl_convert_base_t::get_sp_unit(const pstring &unit)
|
||||
|
||||
double nl_convert_base_t::get_sp_val(const pstring &sin)
|
||||
{
|
||||
auto p = sin.begin();
|
||||
while (p != sin.end() && (m_numberchars.find(*p) != m_numberchars.end()))
|
||||
std::size_t p = 0;
|
||||
while (p < sin.len() && (m_numberchars.find(sin.substr(p, 1)) != pstring::npos))
|
||||
++p;
|
||||
pstring val = sin.left(p);
|
||||
pstring unit = sin.substr(p);
|
||||
@ -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(std::next(m[1].begin(), 3));
|
||||
pins = m[1].left(3);
|
||||
}
|
||||
add_device("QBJT_EB", tt[0], m[0]);
|
||||
add_term(tt[1], tt[0] + "." + pins.code_at(0));
|
||||
@ -381,7 +381,7 @@ void nl_convert_spice_t::process_line(const pstring &line)
|
||||
// last element is component type
|
||||
// FIXME: Parameter
|
||||
|
||||
pstring xname = tt[0].replace(".", "_");
|
||||
pstring xname = tt[0].replace_all(".", "_");
|
||||
pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP";
|
||||
add_device(tname, xname);
|
||||
for (std::size_t i=1; i < tt.size() - 1; i++)
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
|
||||
virtual ~nl_convert_base_t();
|
||||
|
||||
const pstringbuffer &result() { return m_buf.str(); }
|
||||
const pstring &result() { return m_buf.str(); }
|
||||
|
||||
virtual void convert(const pstring &contents) = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user