diff options
author | galaxycrab <UgnineSirdis@ydb.tech> | 2023-11-23 11:26:33 +0300 |
---|---|---|
committer | galaxycrab <UgnineSirdis@ydb.tech> | 2023-11-23 12:01:57 +0300 |
commit | 44354d0fc55926c1d4510d1d2c9c9f6a1a5e9300 (patch) | |
tree | cb4d75cd1c6dbc3da0ed927337fd8d1b6ed9da84 /contrib/libs/libpqxx/src/binarystring.cxx | |
parent | 0e69bf615395fdd48ecee032faaec81bc468b0b8 (diff) | |
download | ydb-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.cxx | 150 |
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}; +} |