From cfb33650607791567274ee6f9029a9e2c0cb210d Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Wed, 22 Nov 2017 15:04:30 +0900 Subject: [PATCH] cxx: Add strbuf support Comes in two fashions: - strbuf_view (read-only) - strbuf (read/write) --- src/Makefile_Cxx.am | 1 + src/bindings/cxx/eina_cxx/Eina.hh | 1 + src/bindings/cxx/eina_cxx/eina_strbuf.hh | 384 +++++++++++++++++++++++ 3 files changed, 386 insertions(+) create mode 100644 src/bindings/cxx/eina_cxx/eina_strbuf.hh diff --git a/src/Makefile_Cxx.am b/src/Makefile_Cxx.am index 24978ddcf1..cf99ea3db3 100644 --- a/src/Makefile_Cxx.am +++ b/src/Makefile_Cxx.am @@ -151,6 +151,7 @@ bindings/cxx/eina_cxx/eina_ptrlist.hh \ bindings/cxx/eina_cxx/eina_range_types.hh \ bindings/cxx/eina_cxx/eina_ref.hh \ bindings/cxx/eina_cxx/eina_stringshare.hh \ +bindings/cxx/eina_cxx/eina_strbuf.hh \ bindings/cxx/eina_cxx/eina_string_view.hh \ bindings/cxx/eina_cxx/eina_thread.hh \ bindings/cxx/eina_cxx/eina_throw.hh \ diff --git a/src/bindings/cxx/eina_cxx/Eina.hh b/src/bindings/cxx/eina_cxx/Eina.hh index de2f374f69..85226d4b53 100644 --- a/src/bindings/cxx/eina_cxx/Eina.hh +++ b/src/bindings/cxx/eina_cxx/Eina.hh @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bindings/cxx/eina_cxx/eina_strbuf.hh b/src/bindings/cxx/eina_cxx/eina_strbuf.hh new file mode 100644 index 0000000000..c81a98f95d --- /dev/null +++ b/src/bindings/cxx/eina_cxx/eina_strbuf.hh @@ -0,0 +1,384 @@ +#ifndef EINA_CXX_STRBUF_HH +#define EINA_CXX_STRBUF_HH + +#include +#include +#include +#include + +#include + +// FIXME: Needs doc, I guess :) + +namespace efl { namespace eina { + +template +struct _strbuf_view_trait +{ + typedef basic_type value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef value_type const& const_reference; + typedef value_type const* const_pointer; + typedef const_pointer const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + + _strbuf_view_trait() = delete; + + /** Create a new view from another _strbuf_view_trait */ + _strbuf_view_trait(_strbuf_view_trait const& other) + : _sb(other._sb) + { + } + + /** Create a new view from an existing Eina_Strbuf */ + _strbuf_view_trait(Eina_Strbuf const* sb) + : _sb(const_cast(sb)) + { + } + + /** + * @brief Tells whether this object contains a real Eina_Strbuf or not + * @return true if wrapping an Eina_Strbuf, false if contains nullptr. + */ + bool empty() const + { + return (_sb != nullptr); + } + + /** + * @brief Get the contained C string + * @return A C-style string (const char*) + */ + const char * c_str() const + { + return ::eina_strbuf_string_get(_sb); + } + + /** + * @brief Convert to a string + * @return A std::string copy + */ + operator std::string() const + { + return std::string(c_str()); + } + + /** + * @brief Get the size of the string. + * @return Number of characters in the string. + */ + size_type size() const + { + return eina_strbuf_length_get(_sb); + } + + /** + * @brief Alias to @ref size() const. + */ + size_type length() const + { + return size(); + } + + /** + * @brief Get a constant iterator pointing to the first character of the string. + * @return Constant iterator to the initial position of the string. + * + * This member function returns a constant iterator pointing to the + * first character of the string. If the string is empty the iterator + * is equal to the one returned by @ref end() const. + */ + const_iterator begin() const + { + return ::eina_strbuf_string_get(_sb); + } + + /** + * @brief Get a constant iterator to the position following the last character of the string. + * @return Constant iterator to the final position of the string. + * + * This member function returns an constant iterator to the position + * following the last character in the string. If the string is empty + * the iterator is equal to the one returned by @ref begin(). + * + * @note Note that attempting to access this position causes undefined + * behavior. + */ + const_iterator end() const + { + return begin() + size(); + } + + /** + * @brief Get a constant reverse iterator pointing to the reverse begin of the string. + * @return Constant reverse iterator pointing to the reverse begin of the string. + * + * This member function returns a constant reverse iterator pointing + * to the last character of the string. If the string is empty the + * returned reverse iterator is the same as the one returned by + * @ref rend() const. + */ + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + /** + * @brief Get a constant reverse iterator pointing to the reverse end of the string. + * @return Constant reverse iterator pointing to the reverse end of the string. + * + * This member function returns a constant reverse iterator pointing + * to the position before the first character of the string. If the + * string is empty the returned iterator is the same as the one + * returned by @ref rbegin() const. + * + * @note Note that attempting to access this position causes undefined + * behavior. + */ + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + /** + * @brief Get a constant iterator to the position following the last character of the string. + * @return Constant iterator to the final position of the string. + * + * This member function works just like @ref end() const. But it is + * granted to always return a constant iterator. + */ + const_iterator cend() const + { + return end(); + } + + /** + * @brief Get a constant reverse iterator pointing to the reverse begin of the string. + * @return Constant reverse iterator pointing to the reverse begin of the string. + * + * This member function works just like @ref rbegin() const. But it is + * granted to always return a constant reverse iterator. + */ + const_reverse_iterator crbegin() const + { + return rbegin(); + } + + /** + * @brief Get a constant reverse iterator pointing to the reverse end of the string. + * @return Constant reverse iterator pointing to the reverse end of the string. + * + * This member function works just like @ref rend() const. But it is + * granted to always return a constant reverse iterator. + */ + const_reverse_iterator crend() const + { + return rend(); + } + + /** + * @brief Get the maximum number of characters a string can hold. + * @return Maximum number of characters a string can hold. + */ + size_type max_size() const + { + return static_cast(-1); + } + + typedef strbuf_type* native_handle_type; + native_handle_type native_handle() const + { + return _sb; + } + +protected: + strbuf_type *_sb; +}; + + +/** A read-only view of an existing Eina_Strbuf. */ +typedef _strbuf_view_trait strbuf_view; + +static struct _strbuf_empty_t {} _strbuf_empty; + + +/** Allocates and manages an Eina_Strbuf, this is a mutable object. */ +struct strbuf : public _strbuf_view_trait +{ + strbuf(const char *str = nullptr) + : _strbuf_view_trait(::eina_strbuf_new()) + { + if (!_sb) EFL_CXX_THROW(std::make_error_code(std::errc::not_enough_memory)); + eina_strbuf_append(_sb, str); + } + + explicit strbuf(_strbuf_empty_t) + : _strbuf_view_trait(nullptr) + { + } + + explicit strbuf(Eina_Strbuf* sb) = delete; + + strbuf(Eina_Strbuf const* sb) + : strbuf(eina_strbuf_string_get(sb)) + { + } + + strbuf(Eina_Strbuf const& sb) + : strbuf(eina_strbuf_string_get(&sb)) + { + } + + strbuf(strbuf_view const& other) + : strbuf(other.native_handle()) + { + } + + strbuf(strbuf&& other) + : strbuf(_strbuf_empty) + { + swap(other); + } + + template + strbuf(S const& str) + : strbuf(std::string(str).c_str()) + { + } + + ~strbuf() + { + ::eina_strbuf_free(_sb); + } + + void swap(strbuf& other) + { + std::swap(_sb, other._sb); + } + + strbuf dup() + { + return strbuf(c_str()); + } + + strbuf& reset() + { + ::eina_strbuf_reset(_sb); + return *this; + } + + template + strbuf& append(S const& str) + { + ::eina_strbuf_append(_sb, std::string(str).c_str()); + return *this; + } + + template + strbuf& append_printf(S const& fmt, Args... args) + { + ::eina_strbuf_append_printf(_sb, std::string(fmt).c_str(), args...); + return *this; + } + + template + strbuf& insert_printf(S const& fmt, size_t pos, Args... args) + { + ::eina_strbuf_insert_printf(_sb, std::string(fmt).c_str(), pos, args...); + return *this; + } + + template + strbuf& append_strftime(S const& fmt, struct tm const& time) + { + ::eina_strbuf_append_strftime(_sb, std::string(fmt).c_str(), &time); + return *this; + } + + template + strbuf& insert_strftime(S const& fmt, size_t pos, struct tm const& time) + { + ::eina_strbuf_insert_printf(_sb, std::string(fmt).c_str(), pos, time); + return *this; + } + + strbuf& trim() + { + ::eina_strbuf_trim(_sb); + return *this; + } + + strbuf& ltrim() + { + ::eina_strbuf_ltrim(_sb); + return *this; + } + + strbuf& rtrim() + { + ::eina_strbuf_rtrim(_sb); + return *this; + } + + // FIXME: add toupper!! + strbuf& tolower() + { + ::eina_strbuf_tolower(_sb); + return *this; + } + + strbuf substr_get(size_t pos, size_t len) + { + strbuf sb(_strbuf_empty); + sb._sb = ::eina_strbuf_substr_get(_sb, pos, len); + return sb; + } + + char * steal() + { + return ::eina_strbuf_string_steal(_sb); + } + + template + strbuf& operator=(S const& other) + { + return reset().append(other); + } + + template + strbuf& operator+=(S const& other) + { + return append(other); + } +}; + + +/** A writeable Eina_Strbuf wrapper, does not allocate or destroy the Eina_Strbuf. */ +struct strbuf_wrapper : public strbuf +{ + strbuf_wrapper() = delete; + strbuf_wrapper(strbuf_view const& other) = delete; + + explicit strbuf_wrapper(Eina_Strbuf* sb) + : strbuf(_strbuf_empty) + { + _sb = sb; + } + + strbuf_wrapper(Eina_Strbuf& sb) + : strbuf_wrapper(&sb) + { + } + + ~strbuf_wrapper() + { + _sb = nullptr; + } +}; + +} } + +#endif