dlopen: switch to new pathfinder class
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.
This commit is contained in:
committed by
Corinna Vinschen
parent
091a0ac120
commit
97974e3076
373
winsup/cygwin/vstrlist.h
Normal file
373
winsup/cygwin/vstrlist.h
Normal file
@@ -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 */
|
Reference in New Issue
Block a user