Instead of find_exec, without changing behaviour use new pathfinder class with new allocator_interface around tmp_pathbuf and new vstrlist class. * pathfinder.h (pathfinder): New file. * vstrlist.h (allocator_interface, allocated_type, vstrlist): New file. * dlfcn.cc (dlopen): Avoid redundant GetModuleHandleExW with RTLD_NOLOAD and RTLD_NODELETE. Switch to new pathfinder class, using (tmp_pathbuf_allocator): New class. (get_full_path_of_dll): Drop.
		
			
				
	
	
		
			374 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			374 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* 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 */
 |