HEX
Server: Apache
System: Linux opal14.opalstack.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
User: curbgloabal_opal (1234)
PHP: 8.1.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //usr/include/pqxx/util.hxx
/*-------------------------------------------------------------------------
 *
 *   FILE
 *	pqxx/util.hxx
 *
 *   DESCRIPTION
 *      Various utility definitions for libpqxx
 *      DO NOT INCLUDE THIS FILE DIRECTLY; include pqxx/util instead.
 *
 * Copyright (c) 2001-2016, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#ifndef PQXX_H_UTIL
#define PQXX_H_UTIL

#include "pqxx/compiler-public.hxx"

#include <cstdio>
#include <cctype>
#include <memory>
#include <stdexcept>
#include <string>
#include <typeinfo>
#include <vector>

#include "pqxx/strconv"


/** @mainpage
 * @author Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * Welcome to libpqxx, the C++ API to the PostgreSQL database management system.
 *
 * Compiling this package requires PostgreSQL to be installed--including the C
 * headers for client development.  The library builds on top of PostgreSQL's
 * standard C API, libpq.  The libpq headers are not needed to compile client
 * programs, however.
 *
 * For a quick introduction to installing and using libpqxx, see the README.md
 * file; a more extensive tutorial is available in doc/html/Tutorial/index.html.
 *
 * The latest information, as well as updates, a mailing list, and a bug
 * reporting system can be found at http://pqxx.org/
 *
 * Some links that should help you find your bearings:
 * \li \ref gettingstarted
 * \li \ref threading
 * \li \ref connection
 * \li \ref transaction
 * \li \ref performance
 *
 * @see http://pqxx.org/
 */

/** @page gettingstarted Getting started
 * The most basic three types in libpqxx are the connection (which inherits its
 * API from pqxx::connection_base and its setup behaviour from
 * pqxx::connectionpolicy), the transaction (derived from
 * pqxx::transaction_base), and the result (pqxx::result).
 *
 * They fit together as follows:
 * \li You connect to the database by creating a
 * connection object (see \ref connection).  The connection type you'll usually
 * want is pqxx::connection.
 * \li You create a transaction object (see \ref transaction) operating on that
 * connection.  You'll usually want the pqxx::work variety.  If you don't want
 * transactional behaviour, use pqxx::nontransaction.  Once you're done you call
 * the transaction's @c commit function to make its work final.  If you don't
 * call this, the work will be rolled back when the transaction object is
 * destroyed.
 * \li Until then, use the transaction's @c exec function to execute queries,
 * which you pass in as simple strings.
 * \li The function returns a pqxx::result object, which acts as a standard
 * container of rows.  Each row in itself acts as a container of fields.  You
 * can use array indexing and/or iterators to access either.
 * \li The field's data is stored as a text string.  You can read it as such
 * using its @c c_str() function, or convert it to other types using its @c as()
 * and @c to() member functions.  These are templated on the destination type:
 * @c myfield.as<int>(); or @c myfield.to(myint);
 * \li After you've closed the transaction, the connection is free to run a next
 * transaction.
 *
 * Here's a very basic example.  It connects to the default database (you'll
 * need to have one set up), queries it for a very simple result, converts it to
 * an @c int, and prints it out.  It also contains some basic error handling.
 *
 * @code
 * #include <iostream>
 * #include <pqxx/pqxx>
 *
 * int main()
 * {
 *   try
 *   {
 *     pqxx::connection c;
 *     pqxx::work w(c);
 *     pqxx::result r = w.exec("SELECT 1");
 *     w.commit();
 *
 *     std::cout << r[0][0].as<int>() << std::endl;
 *   }
 *   catch (const std::exception &e)
 *   {
 *     std::cerr << e.what() << std::endl;
 *     return 1;
 *   }
 * }
 * @endcode
 *
 * This prints the number 1.  Notice that you can keep the result object
 * around after the transaction (or even the connection) has been closed.
 *
 * Here's a slightly more complicated example.  It takes an argument from the
 * command line and retrieves a string with that value.  The interesting part is
 * that it uses the escaping-and-quoting function @c quote() to embed this
 * string value in SQL safely.  It also reads the result field's value as a
 * plain C-style string using its @c c_str() function.
 *
 * @code
 * #include <iostream>
 * #include <pqxx/pqxx>
 *
 * int main(int argc, char *argv[])
 * {
 *   if (!argv[1])
 *   {
 *     std::cerr << "Give me a string!" << std::endl;
 *     return 1;
 *   }
 *   try
 *   {
 *     pqxx::connection c;
 *     pqxx::work w(c);
 *     pqxx::result r = w.exec("SELECT " + w.quote(argv[1]));
 *     w.commit();
 *
 *     std::cout << r[0][0].c_str() << std::endl;
 *   }
 *   catch (const std::exception &e)
 *   {
 *     std::cerr << e.what() << std::endl;
 *     return 1;
 *   }
 * }
 * @endcode
 *
 * You can find more about converting field values to native types, or
 * converting values to strings for use with libpqxx, under
 * \ref stringconversion.  More about getting to the rows and fields of a
 * result is under \ref accessingresults.
 *
 * If you want to handle exceptions thrown by libpqxx in more detail, for
 * example to print the SQL contents of a query that failed, see \ref exception.
 */

/** @page accessingresults Accessing results and result rows
 *
 * Let's say you have a result object.  For example, your program may have done:
 *
 * @code
 * pqxx::result r = w.exec("SELECT * FROM mytable");
 * @endcode
 *
 * Now how do you access the data inside @c r?
 *
 * The simplest way is array indexing.  A result acts as an array of rows,
 * and a row acts as an array of fields.
 *
 * @code
 * const int num_rows = r.size();
 * for (int rownum=0; rownum < num_rows; ++rownum)
 * {
 *   const pqxx::row row = r[rownum];
 *   const int num_cols = row.size();
 *   for (int colnum=0; colnum < num_cols; ++colnum)
 *   {
 *     const pqxx::field field = row[colnum];
 *     std::cout << field.c_str() << '\t';
 *   }
 *
 *   std::cout << std::endl;
 * }
 * @endcode
 *
 * But results and rows also define @c const_iterator types:
 *
 * @code
 * for (pqxx::result::const_iterator row = r.begin();
 *      row != r.end();
 *      ++row)
 *  {
 *    for (pqxx::result::row::const_iterator field = row->begin();
 *         field != row->end();
 *         ++field)
 *      std::cout << field->c_str() << '\t';
 *
 *    std::cout << std::endl;
 *  }
 * @endcode
 *
 * They also have @c const_reverse_iterator types, which iterate backwards from
 * @c rbegin() to @c rend() exclusive.
 *
 * All these iterator types provide one extra bit of convenience that you won't
 * normally find in C++ iterators: referential transparency.  You don't need to
 * dereference them to get to the row or field they refer to.  That is, instead
 * of @c row->end() you can also choose to say @c row.end().  Similarly, you
 * may prefer @c field.c_str() over @c field->c_str().
 *
 * This becomes really helpful with the array-indexing operator.  With regular
 * C++ iterators you would need ugly expressions like @c (*row)[0] or
 * @c row->operator[](0).  With the iterator types defined by the result and
 * row classes you can simply say @c row[0].
 */

/** @page threading Thread safety
 *
 * This library does not contain any locking code to protect objects against
 * simultaneous modification in multi-threaded programs.  There are many
 * different threading interfaces and libpqxx does not dictate your choice.
 *
 * Therefore it is up to you, the user of the library, to ensure that your
 * threaded client programs perform no conflicting operations concurrently.
 *
 * The library does try to avoid non-obvious unsafe operations and so does the
 * underlying libpq.  Here's what you should do to keep your threaded libpqxx
 * application safe:
 *
 * \li Treat a connection, together with any and all objects related to it, as a
 * "world" of its own.  You should generally make sure that the same "world" is
 * never accessed concurrently by multiple threads.  There are a few cases where
 * you don't need to be this careful, however; see below.
 *
 * \li Result sets (pqxx::result) and binary data (pqxx::binarystring)
 * are special.  Copying these objects is very cheap, and you can give the copy
 * to another thread.  Just make sure that no other thread accesses the same
 * copy when it's being assigned to, swapped, cleared, or destroyed.
 *
 * @warning Prior to libpqxx 3.1, or in C++ environments without the standard
 * @c "shared_ptr" smart pointer type, copying, assigning, or destroying a
 * pqxx::result or pqxx::binarystring could also affect any other other object
 * of the same type referring to the same underlying data.
 *
 * Use @c pqxx::describe_thread_safety to find out at runtime what level of
 * thread safety is implemented in your build and version of libpqxx.  It
 * returns a pqxx::thread_safety_model describing what you can and cannot rely
 * on.  A command-line utility @c tools/pqxxthreadsafety prints out the same
 * information.
 */

/// The home of all libpqxx classes, functions, templates, etc.
namespace pqxx {}

#include <pqxx/internal/libpq-forward.hxx>


namespace pqxx
{
/// Descriptor of library's thread-safety model.
/** This describes what the library knows about various risks to thread-safety.
 */
struct PQXX_LIBEXPORT thread_safety_model
{
  /// Does standard C library have a thread-safe alternative to @c strerror?
  /** If not, its @c strerror implementation may still be thread-safe.  Check
   * your compiler's manual.
   *
   * Without @c strerror_r (@c strerror_s in Visual C++) or a thread-safe @c
   * strerror, the library can't safely obtain descriptions of certain run-time
   * errors.  In that case, your application must serialize all use of libpqxx.
   */
  bool have_safe_strerror;

  /// Is the underlying libpq build thread-safe?
  /** A @c "false" here may mean one of two things: either the libpq build is
   * not thread-safe, or it is a thread-safe build of an older version that did
   * not offer thread-safety information.
   *
   * In that case, the best fix is to rebuild libpqxx against (a thread-safe
   * build of) a newer libpq version.
   */
  bool safe_libpq;

  /// Is canceling queries thread-safe?
  /** If not, avoid use of the pqxx::pipeline class in threaded programs.  Or
   * better, rebuild libpqxx against a newer libpq version.
   */
  bool safe_query_cancel;

  /// Are copies of pqxx::result and pqxx::binarystring objects thread-safe?
  /** If @c true, it's safe to copy an object of either of these types (copying
   * these is done very efficiently, so don't worry about data size) and hand
   * the copy off to another thread.  The other thread may access the copy
   * freely without any concurrency concerns.
   */
  bool safe_result_copy;

  /// Is Kerberos thread-safe?
  /** @warning Is currently always @c false.
   *
   * If your application uses Kerberos, all accesses to libpqxx or Kerberos must
   * be serialized.  Confine their use to a single thread, or protect it with a
   * global lock.
   */
  bool safe_kerberos;

  /// A human-readable description of any thread-safety issues.
  std::string description;
};

/// Describe thread safety available in this build.
PQXX_LIBEXPORT thread_safety_model describe_thread_safety() PQXX_NOEXCEPT;

/// The "null" oid
const oid oid_none = 0;

/// Container of items with easy contents initialization and string rendering
/** Designed as a wrapper around an arbitrary container type, this class lets
 * you easily create a container object and provide its contents in the same
 * line.  Regular addition methods such as push_back() will also still work, but
 * you can now write things like
 * @code
 *  items<int> numbers; numbers(1)(2)(3)(4);
 * @endcode
 *
 * Up to five elements may be specified directly as constructor arguments, e.g.
 * @code
 * items<int> numbers(1,2,3,4);
 * @endcode
 *
 * One thing that cannot be done with this simple class is create const objects
 * with nontrivial contents.  This is because the function invocation operator
 * (which is being used to add items) modifies the container rather than
 * creating a new one.  This was done to keep performance within reasonable
 * bounds.
 *
 * @warning This class may see substantial change in its interface before it
 * stabilizes.  Do not count on it remaining the way it is.
 */
template<typename T=std::string, typename CONT=std::vector<T> >
class items : public CONT
{
public:
  /// Create empty items list
  items() : CONT() {}							//[t0]
  /// Create items list with one element
  explicit items(const T &t) : CONT() { this->push_back(t); }		//[t0]
  items(const T &t1, const T &t2) : CONT()				//[t0]
	{ this->push_back(t1); this->push_back(t2); }
  items(const T &t1, const T &t2, const T &t3) : CONT()			//[t0]
	{ this->push_back(t1); this->push_back(t2); this->push_back(t3); }
  items(const T &t1, const T &t2, const T &t3, const T &t4) : CONT()	//[t0]
  {
    this->push_back(t1);
    this->push_back(t2);
    this->push_back(t3);
    this->push_back(t4);
  }
  items(const T&t1,const T&t2,const T&t3,const T&t4,const T&t5):CONT()	//[t0]
  {
    this->push_back(t1);
    this->push_back(t2);
    this->push_back(t3);
    this->push_back(t4);
    this->push_back(t5);
  }
  /// Copy container
  items(const CONT &c) : CONT(c) {}					//[t0]

  /// Add element to items list
  items &operator()(const T &t)						//[t0]
  {
    this->push_back(t);
    return *this;
  }
};


namespace internal
{
// TODO: Does standard library provide a ready-made version of this?
/// Functor: dereference iterator
template<typename ITER> struct dereference
{
  typename ITER::value_type operator()(ITER i) const { return *i; }
};
template<typename T> struct deref_ptr { T operator()(T *i) const {return *i;} };
} // namespace internal


/// Access iterators using ACCESS functor, returning separator-separated list
/**
 * @param sep separator string (to be placed between items)
 * @param begin beginning of items sequence
 * @param end end of items sequence
 * @param access functor defining how to dereference sequence elements
 */
template<typename ITER, typename ACCESS> inline
std::string separated_list(const std::string &sep,			//[t0]
    ITER begin,
    ITER end,
    ACCESS access)
{
  std::string result;
  if (begin != end)
  {
    result = to_string(access(begin));
    for (++begin; begin != end; ++begin)
    {
      result += sep;
      result += to_string(access(begin));
    }
  }
  return result;
}

/**
 * @defgroup utility Utility functions
 */
//@{

/// Render sequence as a string, using given separator between items
template<typename ITER> inline std::string
separated_list(const std::string &sep, ITER begin, ITER end)		//[t0]
	{ return separated_list(sep,begin,end,internal::dereference<ITER>()); }


/// Render array as a string, using given separator between items
template<typename OBJ> inline std::string
separated_list(const std::string &sep, OBJ *begin, OBJ *end)		//[t0]
	{ return separated_list(sep,begin,end,internal::deref_ptr<OBJ>()); }


/// Render items in a container as a string, using given separator
template<typename CONTAINER> inline std::string
separated_list(const std::string &sep, const CONTAINER &c)		//[t10]
	{ return separated_list(sep, c.begin(), c.end()); }
//@}

/// Private namespace for libpqxx's internal use; do not access
/** This namespace hides definitions internal to libpqxx.  These are not
 * supposed to be used by client programs, and they may change at any time
 * without notice.
 *
 * Conversely, if you find something in this namespace tremendously useful, by
 * all means do lodge a request for its publication.
 *
 * @warning Here be dragons!
 */
namespace internal
{
typedef unsigned long result_size_type;
typedef long result_difference_type;
} // namespace internal


namespace internal
{
PQXX_LIBEXPORT void freepqmem(const void *) PQXX_NOEXCEPT;
template<typename P> inline void freepqmem_templated(P *p) PQXX_NOEXCEPT
{
  freepqmem(p);
}

PQXX_LIBEXPORT void freemallocmem(const void *) PQXX_NOEXCEPT;
template<typename P> inline void freemallocmem_templated(P *p) PQXX_NOEXCEPT
{
  freemallocmem(p);
}


#ifdef PQXX_HAVE_SHARED_PTR

/// Reference-counted smart pointer to libpq-allocated object
template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
  class PQAlloc
{
public:
  typedef T content_type;
  PQAlloc() PQXX_NOEXCEPT : m_ptr() {}
  PQAlloc(const PQAlloc &rhs) PQXX_NOEXCEPT : m_ptr(rhs.m_ptr) {}
  explicit PQAlloc(T *t) : m_ptr(t, DELETER) {}

  T *get() const PQXX_NOEXCEPT { return m_ptr.get(); }
  PQAlloc &operator=(const PQAlloc &rhs) PQXX_NOEXCEPT
  {
    m_ptr = rhs.m_ptr;
    return *this;
  }

#if __cplusplus >= 201103L
  PQAlloc(PQAlloc &&) =default;
  PQAlloc &operator=(PQAlloc &&) =default;
#endif

  T *operator->() const PQXX_NOEXCEPT { return m_ptr.get(); }
  T &operator*() const PQXX_NOEXCEPT { return *m_ptr; }
  void reset() PQXX_NOEXCEPT { m_ptr.reset(); }
  void swap(PQAlloc &other) PQXX_NOEXCEPT { m_ptr.swap(other.m_ptr); }

private:
  std::shared_ptr<T> m_ptr;
};

#else // !PQXX_HAVE_SHARED_PTR

/// Helper class used in reference counting (doubly-linked circular list)
/// Reference-counted smart-pointer for libpq-allocated resources.
class PQXX_LIBEXPORT refcount
{
  refcount *volatile m_l, *volatile m_r;

public:
  refcount();
  ~refcount();

  /// Create additional reference based on existing refcount object
  void makeref(refcount &) PQXX_NOEXCEPT;

  /// Drop this reference; return whether we were the last reference
  bool loseref() PQXX_NOEXCEPT;

private:
  /// Not allowed
  refcount(const refcount &);
  /// Not allowed
  refcount &operator=(const refcount &);
};


/// Reference-counted smart pointer to libpq-allocated object
/** Keep track of a libpq-allocated object, and free it once all references to
 * it have died.
 *
 * The memory is freed with @c PQfreemem() by default.  This matters on Windows,
 * where apparently under some circumstances, memory allocated by a DLL must be
 * freed by the same DLL.
 *
 * @warning Copying, swapping, and destroying PQAlloc objects that refer to the
 * same underlying libpq-allocated block is <em>not thread-safe</em>.  If you
 * wish to pass reference-counted objects around between threads, make sure that
 * each of these operations is protected against concurrency with similar
 * operations on the same object--or other copies of the same object.
 */
template<typename T, void (*DELETER)(T *) = freepqmem_templated<T> >
class PQAlloc
{
  T *m_Obj;
  mutable refcount m_rc;
public:
  typedef T content_type;

  PQAlloc() PQXX_NOEXCEPT : m_Obj(0), m_rc() {}
  PQAlloc(const PQAlloc &rhs) PQXX_NOEXCEPT : m_Obj(0), m_rc() { makeref(rhs); }
  ~PQAlloc() PQXX_NOEXCEPT { loseref(); }

  PQAlloc &operator=(const PQAlloc &rhs) PQXX_NOEXCEPT
	{redoref(rhs); return *this;}

  /// Assume ownership of a pointer
  /** @warning Don't to this more than once for a given object!
   */
  explicit PQAlloc(T *obj) PQXX_NOEXCEPT : m_Obj(obj), m_rc() {}

  void swap(PQAlloc &rhs) PQXX_NOEXCEPT
  {
    PQAlloc tmp(*this);
    *this = rhs;
    rhs = tmp;
  }

  /// Is this pointer non-null?
  operator bool() const PQXX_NOEXCEPT { return m_Obj != 0; }

  /// Is this pointer null?
  bool operator!() const PQXX_NOEXCEPT { return !m_Obj; }

  /// Dereference pointer
  /** Throws a logic_error if the pointer is null.
   */
  T *operator->() const
  {
    if (!m_Obj) throw std::logic_error("Null pointer dereferenced");
    return m_Obj;
  }

  /// Dereference pointer
  /** Throws a logic_error if the pointer is null.
   */
  T &operator*() const { return *operator->(); }

  /// Obtain underlying pointer
  /** Ownership of the pointer's memory remains with the PQAlloc object
   */
  T *get() const PQXX_NOEXCEPT { return m_Obj; }

  void reset() PQXX_NOEXCEPT { loseref(); }

private:
  void makeref(T *p) PQXX_NOEXCEPT { m_Obj = p; }

  void makeref(const PQAlloc &rhs) PQXX_NOEXCEPT
  {
    m_Obj = rhs.m_Obj;
    m_rc.makeref(rhs.m_rc);
  }

  /// Free and reset current pointer (if any)
  void loseref() PQXX_NOEXCEPT
  {
    if (m_rc.loseref() && m_Obj) DELETER(m_Obj);
    m_Obj = 0;
  }

  void redoref(const PQAlloc &rhs) PQXX_NOEXCEPT
	{ if (rhs.m_Obj != m_Obj) { loseref(); makeref(rhs); } }
  void redoref(T *obj) PQXX_NOEXCEPT
	{ if (obj != m_Obj) { loseref(); makeref(obj); } }
};

#endif // PQXX_HAVE_SHARED_PTR


class PQXX_LIBEXPORT namedclass
{
public:
  namedclass(const std::string &Classname, const std::string &Name="") :
    m_Classname(Classname),
    m_Name(Name)
  {
  }

  const std::string &name() const PQXX_NOEXCEPT { return m_Name; }	//[t1]
  const std::string &classname() const PQXX_NOEXCEPT			//[t73]
	{return m_Classname;}
  std::string description() const;

private:
  std::string m_Classname, m_Name;
};


void CheckUniqueRegistration(const namedclass *New, const namedclass *Old);
void CheckUniqueUnregistration(const namedclass *New, const namedclass *Old);


/// Ensure proper opening/closing of GUEST objects related to a "host" object
/** Only a single GUEST may exist for a single host at any given time.  GUEST
 * must be derived from namedclass.
 */
template<typename GUEST>
class unique
{
public:
  unique() : m_Guest(0) {}

  GUEST *get() const PQXX_NOEXCEPT { return m_Guest; }

  void Register(GUEST *G)
  {
    CheckUniqueRegistration(G, m_Guest);
    m_Guest = G;
  }

  void Unregister(GUEST *G)
  {
    CheckUniqueUnregistration(G, m_Guest);
    m_Guest = 0;
  }

private:
  GUEST *m_Guest;

  /// Not allowed
  unique(const unique &);
  /// Not allowed
  unique &operator=(const unique &);
};

/// Sleep for the given number of seconds
/** May return early, e.g. when interrupted by a signal.  Completes instantly if
 * a zero or negative sleep time is requested.
 */
PQXX_LIBEXPORT void sleep_seconds(int);

/// Work around problem with library export directives and pointers
typedef const char *cstring;

/// Human-readable description for error code, possibly using given buffer
/** Wrapper for @c strerror() or thread-safe variant, as available.  The
 * default code copies the string to the provided buffer, but this may not
 * always be necessary.  The result is guaranteed to remain usable for as long
 * as the given buffer does.
 * @param err system error code as copied from errno
 * @param buf caller-provided buffer for message to be stored in, if needed
 * @param len usable size (in bytes) of provided buffer
 * @return human-readable error string, which may or may not reside in buf
 */
PQXX_LIBEXPORT cstring strerror_wrapper(int err, char buf[], std::size_t len)
  PQXX_NOEXCEPT;


/// Commonly used SQL commands
extern const char sql_begin_work[], sql_commit_work[], sql_rollback_work[];


/// Wrapper for std::distance; not all platforms have std::distance().
template<typename T> inline std::ptrdiff_t distance(T first, T last)
{
#ifdef PQXX_HAVE_DISTANCE
  return std::distance(first, last);
#else
  // Naive implementation.  All we really need for now.
  std::ptrdiff_t d;
  for (d=0; first != last; ++d) ++first;
  return d;
#endif
}

} // namespace internal
} // namespace pqxx

#endif