diff options
Diffstat (limited to 'src/lib/netlist/plib/pstring.h')
-rw-r--r-- | src/lib/netlist/plib/pstring.h | 298 |
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 { |