Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/local_includes/vstrlist.h')
-rw-r--r--winsup/cygwin/local_includes/vstrlist.h373
1 files changed, 373 insertions, 0 deletions
diff --git a/winsup/cygwin/local_includes/vstrlist.h b/winsup/cygwin/local_includes/vstrlist.h
new file mode 100644
index 000000000..d5ad717c3
--- /dev/null
+++ b/winsup/cygwin/local_includes/vstrlist.h
@@ -0,0 +1,373 @@
+/* vstrlist.h: class vstrlist
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#ifdef __cplusplus
+
+struct allocator_interface
+{
+ virtual void * alloc (size_t) = 0;
+ virtual void free (void *) = 0;
+};
+
+
+/* The allocated_type makes sure to use the free () method of the
+ same allocator_interface than the alloc () method was used of.
+
+ Stores the allocator_interface address before the real object,
+ to hide it from (construction & destruction of) real object. */
+class allocated_type
+{
+ union allocator_store
+ {
+ allocator_interface * allocator_;
+ char alignment_[8];
+
+ union pointer
+ {
+ void * vptr;
+ allocator_store * real;
+ };
+ };
+
+public:
+ void * operator new (size_t class_size, allocator_interface & allocator)
+ {
+ allocator_store::pointer astore;
+ astore.vptr = allocator.alloc (sizeof (allocator_store) + class_size);
+ astore.real->allocator_ = &allocator;
+ ++ astore.real;
+ return astore.vptr;
+ }
+
+ void operator delete (void * p)
+ {
+ allocator_store::pointer astore;
+ astore.vptr = p;
+ -- astore.real;
+ astore.real->allocator_->free (astore.vptr);
+ }
+};
+
+
+/* Double linked list of char arrays, each being a string buffer,
+ which's final buffer size and initial string content is defined
+ by a NULL terminated variable argument list of STRING+LEN pairs,
+ where each STRING (up to LEN) is concatenated for the initial
+ string buffer content, and each LEN is added to the final size
+ of the allocated string buffer.
+ If LEN is -1, strlen(STRING) is used for LEN.
+
+ Needs:
+ An implementation of the allocator_interface.
+
+ Provides:
+ iterator:
+ short name for the string_iterator
+ string_iterator:
+ provides readonly access via member methods:
+ string (): readonly string buffer
+ stringlength (): length (readonly) of initial string
+ buffer_iterator:
+ extends string_iterator
+ provides writeable access via member methods:
+ buffer (): writeable string buffer
+ bufferlength (): length (readonly) of allocated buffer
+
+ Usage sample:
+ char * text = "snipe";
+ vstrlist l;
+ l.appendv (text, 4, text+3, 2, "", 2, NULL);
+ buffer_iterator it (l.begin ());
+ strcpy (it->buffer () + it->stringlength (), "ts");
+ printf ("Sample result is: '%s'", it->string ());
+ Sample result is: 'snippets' */
+class vstrlist
+{
+public:
+ class member
+ : public allocated_type
+ {
+ friend class vstrlist;
+ friend class string_iterator;
+
+ member * prev_;
+ member * next_;
+ size_t bufferlength_;
+ size_t stringlength_;
+ char buffer_[1]; /* we always have space for the trailing zero */
+
+ /* no copy, just swap */
+ member (member const &);
+ member & operator = (member const &);
+
+ /* anchor */
+ void * operator new (size_t class_size, allocator_interface & allocator)
+ {
+ return allocated_type::operator new (class_size, allocator);
+ }
+
+ /* anchor */
+ member ()
+ : allocated_type ()
+ , prev_ (this)
+ , next_ (this)
+ , bufferlength_ (0)
+ , stringlength_ (0)
+ , buffer_ ()
+ {}
+
+ /* entry: determine memory size from args */
+ void * operator new (size_t class_size, allocator_interface & allocator,
+ char const * part0, va_list parts)
+ {
+ char const * part = part0;
+ va_list partsdup;
+ va_copy (partsdup, parts);
+ while (part)
+ {
+ int partlen = va_arg (partsdup, int);
+ if (partlen < 0)
+ partlen = strlen (part);
+ class_size += partlen;
+ part = va_arg (partsdup, char const *);
+ }
+ va_end (partsdup);
+
+ return allocated_type::operator new (class_size, allocator);
+ }
+
+ /* entry: instantly insert into list */
+ member (member * before, char const * part0, va_list parts)
+ : allocated_type ()
+ , prev_ (NULL)
+ , next_ (NULL)
+ , bufferlength_ (0)
+ , stringlength_ ()
+ , buffer_ ()
+ {
+ prev_ = before->prev_;
+ next_ = before;
+
+ prev_->next_ = this;
+ next_->prev_ = this;
+
+ char * dest = buffer_;
+ char const * part = part0;
+ va_list partsdup;
+ va_copy (partsdup, parts);
+ while (part)
+ {
+ int partlen = va_arg (partsdup, int);
+ if (partlen < 0)
+ {
+ char * old = dest;
+ dest = stpcpy (old, part);
+ partlen = dest - old;
+ }
+ else
+ dest = stpncpy (dest, part, partlen);
+ bufferlength_ += partlen;
+ part = va_arg (partsdup, const char *);
+ }
+ va_end (partsdup);
+ *dest = (char)0;
+ stringlength_ = dest - buffer_;
+ if (bufferlength_ > stringlength_)
+ memset (++dest, 0, bufferlength_ - stringlength_);
+ }
+
+ /* remove entry from list */
+ ~member ()
+ {
+ member * next = next_;
+ member * prev = prev_;
+ if (next)
+ next->prev_ = prev;
+ if (prev)
+ prev->next_ = next;
+ prev_ = NULL;
+ next_ = NULL;
+ }
+
+ public:
+ member const * next () const { return next_; }
+ member * next () { return next_; }
+ member const * prev () const { return next_; }
+ member * prev () { return next_; }
+
+ /* readonly access */
+ char const * string () const { return buffer_; }
+ size_t stringlength () const { return stringlength_; }
+
+ /* writeable access */
+ char * buffer () { return buffer_; }
+ size_t bufferlength () { return bufferlength_; }
+ };
+
+ /* readonly access */
+ class string_iterator
+ {
+ friend class vstrlist;
+ friend class buffer_iterator;
+
+ member * current_;
+
+ string_iterator ();
+
+ string_iterator (member * current)
+ : current_ (current)
+ {}
+
+ public:
+ string_iterator (string_iterator const & rhs)
+ : current_ (rhs.current_)
+ {}
+
+ string_iterator & operator = (string_iterator const & rhs)
+ {
+ current_ = rhs.current_;
+ return *this;
+ }
+
+ string_iterator & operator ++ ()
+ {
+ current_ = current_->next ();
+ return *this;
+ }
+
+ string_iterator operator ++ (int)
+ {
+ string_iterator ret (*this);
+ current_ = current_->next ();
+ return ret;
+ }
+
+ string_iterator & operator -- ()
+ {
+ current_ = current_->prev ();
+ return *this;
+ }
+
+ string_iterator operator -- (int)
+ {
+ string_iterator ret (*this);
+ current_ = current_->prev ();
+ return ret;
+ }
+
+ bool operator == (string_iterator const & rhs) const
+ {
+ return current_ == rhs.current_;
+ }
+
+ bool operator != (string_iterator const & rhs) const
+ {
+ return current_ != rhs.current_;
+ }
+
+ /* readonly member access */
+ member const & operator * () const { return *current_; }
+ member const * operator -> () const { return current_; }
+
+ void remove ()
+ {
+ member * old = current_;
+ ++ *this;
+ delete old;
+ }
+ };
+
+ /* writeable access */
+ class buffer_iterator
+ : public string_iterator
+ {
+ public:
+ explicit /* can be used with vstrlist.begin () */
+ buffer_iterator (string_iterator const & begin)
+ : string_iterator (begin)
+ {}
+
+ buffer_iterator (buffer_iterator const & rhs)
+ : string_iterator (rhs)
+ {}
+
+ buffer_iterator & operator = (buffer_iterator const & rhs)
+ {
+ string_iterator::operator = (rhs);
+ return *this;
+ }
+
+ /* writeable member access */
+ member & operator * () const { return *current_; }
+ member * operator -> () const { return current_; }
+ };
+
+private:
+ allocator_interface & allocator_;
+ member * anchor_;
+
+ /* not without an allocator */
+ vstrlist ();
+
+ /* no copy, just swap () */
+ vstrlist (vstrlist const &);
+ vstrlist & operator = (vstrlist const &);
+
+public:
+ /* iterator is the string_iterator */
+ typedef class string_iterator iterator;
+
+ iterator begin () { return iterator (anchor_->next ()); }
+ iterator end () { return iterator (anchor_ ); }
+ iterator rbegin () { return iterator (anchor_->prev ()); }
+ iterator rend () { return iterator (anchor_ ); }
+
+ vstrlist (allocator_interface & a)
+ : allocator_ (a)
+ , anchor_ (NULL) /* exception safety */
+ {
+ anchor_ = new (allocator_) member ();
+ }
+
+ ~vstrlist ()
+ {
+ if (anchor_ != NULL)
+ {
+ for (iterator it = begin (); it != end (); it.remove ());
+ delete anchor_;
+ }
+ }
+
+ void swap (vstrlist & that)
+ {
+ allocator_interface & a = allocator_;
+ member * m = anchor_;
+ allocator_ = that.allocator_;
+ anchor_ = that.anchor_;
+ that.allocator_ = a;
+ that.anchor_ = m;
+ }
+
+ string_iterator appendv (char const * part0, va_list parts)
+ {
+ member * ret = new (allocator_, part0, parts)
+ member (anchor_, part0, parts);
+ return string_iterator (ret);
+ }
+
+ string_iterator appendv (char const * part0, ...)
+ {
+ va_list parts;
+ va_start (parts, part0);
+ string_iterator ret = appendv (part0, parts);
+ va_end (parts);
+ return ret;
+ }
+};
+
+#endif /* __cplusplus */