summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/pstring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/pstring.h')
-rw-r--r--src/lib/netlist/plib/pstring.h298
1 files changed, 103 insertions, 195 deletions
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 7bb037b42cd..94e8231b9d3 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -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 std::size_t size_type;
+ 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
- {
- return traits::len(m_ptr);
- }
-
- 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; }
+ size_type len() const { return traits_type::len(m_str); }
- 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()); }
+ /* the following are extensions to <string> */
- 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 left(size_type len) const { return substr(0, len); }
+ pstring_t right(size_type nlen) const
+ {
+ return nlen >= len() ? pstring_t(*this) : substr(len() - nlen, nlen);
+ }
- 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 ltrim(const pstring_t &ws = pstring_t(" \t\n\r")) const
+ {
+ return substr(find_first_not_of(ws));
+ }
- const_iterator find_first_not_of(const pstring_t &no) const;
- const_iterator find_last_not_of(const pstring_t &no) const;
+ 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 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 trim(const pstring_t &ws = pstring_t(" \t\n\r")) const { return this->ltrim(ws).rtrim(ws); }
- const pstring_t rpad(const pstring_t &ws, const size_type cnt) 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)); }
+ code_t code_at(const size_type pos) const {return F::code(F::nthcode(m_str.c_str(),pos)); }
- const pstring_t ucase() 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
{