aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libpqxx/src/binarystring.cxx
diff options
context:
space:
mode:
authorgalaxycrab <UgnineSirdis@ydb.tech>2023-11-23 11:26:33 +0300
committergalaxycrab <UgnineSirdis@ydb.tech>2023-11-23 12:01:57 +0300
commit44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300 (patch)
treecb4d75cd1c6dbc3da0ed927337fd8d1b6ed9da84 /contrib/libs/libpqxx/src/binarystring.cxx
parent0e69bf615395fdd48ecee032faaec81bc468b0b8 (diff)
downloadydb-44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300.tar.gz
YQ Connector:test INNER JOIN
Diffstat (limited to 'contrib/libs/libpqxx/src/binarystring.cxx')
-rw-r--r--contrib/libs/libpqxx/src/binarystring.cxx150
1 files changed, 150 insertions, 0 deletions
diff --git a/contrib/libs/libpqxx/src/binarystring.cxx b/contrib/libs/libpqxx/src/binarystring.cxx
new file mode 100644
index 0000000000..0091f48baf
--- /dev/null
+++ b/contrib/libs/libpqxx/src/binarystring.cxx
@@ -0,0 +1,150 @@
+/** Implementation of bytea (binary string) conversions.
+ *
+ * Copyright (c) 2000-2019, Jeroen T. Vermeulen.
+ *
+ * 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.
+ */
+#include "pqxx/compiler-internal.hxx"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <new>
+#include <stdexcept>
+
+extern "C"
+{
+#include "libpq-fe.h"
+}
+
+#include "pqxx/binarystring"
+#include "pqxx/field"
+
+
+using namespace pqxx::internal;
+
+namespace
+{
+using unsigned_char = unsigned char;
+using buffer = std::pair<unsigned char *, size_t>;
+
+
+buffer to_buffer(const void *data, size_t len)
+{
+ void *const output{malloc(len + 1)};
+ if (output == nullptr) throw std::bad_alloc{};
+ static_cast<char *>(output)[len] = '\0';
+ memcpy(static_cast<char *>(output), data, len);
+ return buffer{static_cast<unsigned char *>(output), len};
+}
+
+
+buffer to_buffer(const std::string &source)
+{
+ return to_buffer(source.c_str(), source.size());
+}
+
+
+
+buffer unescape(const unsigned char escaped[])
+{
+#ifdef _WIN32
+ /* On Windows only, the return value from PQunescapeBytea() must be freed
+ * using PQfreemem. Copy to a buffer allocated by libpqxx, so that the
+ * binarystring's buffer can be freed uniformly,
+ */
+ size_t unescaped_len = 0;
+ // TODO: Use make_unique once we require C++14. Sooo much easier.
+ std::unique_ptr<unsigned char, void(*)(unsigned char *)> A(
+ PQunescapeBytea(const_cast<unsigned char *>(escaped), &unescaped_len),
+ freepqmem_templated<unsigned char>);
+ void *data = A.get();
+ if (data == nullptr) throw std::bad_alloc{};
+ return to_buffer(data, unescaped_len);
+#else
+ /* On non-Windows platforms, it's okay to free libpq-allocated memory using
+ * free(). No extra copy needed.
+ */
+ buffer unescaped;
+ unescaped.first = PQunescapeBytea(
+ const_cast<unsigned char *>(escaped), &unescaped.second);
+ if (unescaped.first == nullptr) throw std::bad_alloc{};
+ return unescaped;
+#endif
+}
+
+} // namespace
+
+
+pqxx::binarystring::binarystring(const field &F) :
+ m_buf{make_smart_pointer()},
+ m_size{0}
+{
+ buffer unescaped{unescape(reinterpret_cast<const_pointer>(F.c_str()))};
+ m_buf = make_smart_pointer(unescaped.first);
+ m_size = unescaped.second;
+}
+
+
+pqxx::binarystring::binarystring(const std::string &s) :
+ m_buf{make_smart_pointer()},
+ m_size{s.size()}
+{
+ m_buf = make_smart_pointer(to_buffer(s).first);
+}
+
+
+pqxx::binarystring::binarystring(const void *binary_data, size_t len) :
+ m_buf{make_smart_pointer()},
+ m_size{len}
+{
+ m_buf = make_smart_pointer(to_buffer(binary_data, len).first);
+}
+
+
+bool pqxx::binarystring::operator==(const binarystring &rhs) const noexcept
+{
+ if (rhs.size() != size()) return false;
+ return std::memcmp(data(), rhs.data(), size()) == 0;
+}
+
+
+pqxx::binarystring &pqxx::binarystring::operator=(const binarystring &rhs)
+{
+ m_buf = rhs.m_buf;
+ m_size = rhs.m_size;
+ return *this;
+}
+
+
+pqxx::binarystring::const_reference pqxx::binarystring::at(size_type n) const
+{
+ if (n >= m_size)
+ {
+ if (m_size == 0)
+ throw std::out_of_range{"Accessing empty binarystring"};
+ throw std::out_of_range{
+ "binarystring index out of range: " +
+ to_string(n) + " (should be below " + to_string(m_size) + ")"};
+ }
+ return data()[n];
+}
+
+
+void pqxx::binarystring::swap(binarystring &rhs)
+{
+ m_buf.swap(rhs.m_buf);
+
+ // This part very obviously can't go wrong, so do it last
+ const auto s = m_size;
+ m_size = rhs.m_size;
+ rhs.m_size = s;
+}
+
+
+std::string pqxx::binarystring::str() const
+{
+ return std::string{get(), m_size};
+}