audio_trans/orm_lib/inc/drogon/orm/Field.h

277 lines
6.6 KiB
C++

/**
*
* @file Field.h
* @author An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
// Taken from libpqxx and modified.
// The license for libpqxx can be found in the COPYING file.
#pragma once
#include <drogon/exports.h>
#include <drogon/utils/string_view.h>
#include <drogon/orm/ArrayParser.h>
#include <drogon/orm/Result.h>
#include <drogon/orm/Row.h>
#include <trantor/utils/Logger.h>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#ifdef __linux__
#include <arpa/inet.h>
#endif
namespace drogon
{
namespace orm
{
/// Reference to a field in a result set.
/**
* A field represents one entry in a row. It represents an actual value
* in the result set, and can be converted to various types.
*/
class DROGON_EXPORT Field
{
public:
using SizeType = unsigned long;
/// Column name
const char *name() const;
/// Is this field's value null?
bool isNull() const;
/// Read as plain C string
/**
* Since the field's data is stored internally in the form of a
* zero-terminated C string, this is the fastest way to read it. Use the
* to() or as() functions to convert the string to other types such as
* @c int, or to C++ strings.
*/
const char *c_str() const;
/// Get the length of the plain C string
size_t length() const
{
return result_.getLength(row_, column_);
}
/// Convert to a type T value
template <typename T>
T as() const
{
if (isNull())
return T();
auto data_ = result_.getValue(row_, column_);
// auto dataLength_ = result_.getLength(row_, column_);
// For binary format!
// if (dataLength_ == 1)
// {
// return *data_;
// }
// else if (dataLength_ == 4)
// {
// const int32_t *n = (int32_t *)data_;
// return ntohl(*n);
// }
// else if (dataLength_ == 8)
// {
// const int64_t *n = (int64_t *)data_;
// return ntohll(*n);
// }
// return 0;
T value = T();
if (data_)
{
try
{
std::stringstream ss(data_);
ss >> value;
}
catch (...)
{
LOG_DEBUG << "Type error";
}
}
return value;
}
/// Parse the field as an SQL array.
/**
* Call the parser to retrieve values (and structure) from the array.
*
* Make sure the @c result object stays alive until parsing is finished. If
* you keep the @c row of @c field object alive, it will keep the @c result
* object alive as well.
*/
ArrayParser getArrayParser() const
{
return ArrayParser(result_.getValue(row_, column_));
}
template <typename T>
std::vector<std::shared_ptr<T>> asArray() const
{
std::vector<std::shared_ptr<T>> ret;
auto arrParser = getArrayParser();
while (1)
{
auto arrVal = arrParser.getNext();
if (arrVal.first == ArrayParser::juncture::done)
{
break;
}
if (arrVal.first == ArrayParser::juncture::string_value)
{
T val;
std::stringstream ss(std::move(arrVal.second));
ss >> val;
ret.push_back(std::shared_ptr<T>(new T(val)));
}
else if (arrVal.first == ArrayParser::juncture::null_value)
{
ret.push_back(std::shared_ptr<T>());
}
}
return ret;
}
protected:
Result::SizeType row_;
/**
* Column number
* You'd expect this to be a size_t, but due to the way reverse iterators
* are related to regular iterators, it must be allowed to underflow to -1.
*/
long column_;
friend class Row;
Field(const Row &row, Row::SizeType columnNum) noexcept;
private:
const Result result_;
};
template <>
DROGON_EXPORT std::string Field::as<std::string>() const;
template <>
DROGON_EXPORT const char *Field::as<const char *>() const;
template <>
DROGON_EXPORT char *Field::as<char *>() const;
template <>
DROGON_EXPORT std::vector<char> Field::as<std::vector<char>>() const;
template <>
inline drogon::string_view Field::as<drogon::string_view>() const
{
auto first = result_.getValue(row_, column_);
auto length = result_.getLength(row_, column_);
return {first, length};
}
template <>
inline float Field::as<float>() const
{
if (isNull())
return 0.0;
return std::stof(result_.getValue(row_, column_));
}
template <>
inline double Field::as<double>() const
{
if (isNull())
return 0.0;
return std::stod(result_.getValue(row_, column_));
}
template <>
inline bool Field::as<bool>() const
{
if (result_.getLength(row_, column_) != 1)
{
return false;
}
auto value = result_.getValue(row_, column_);
if (*value == 't' || *value == '1')
return true;
return false;
}
template <>
inline int Field::as<int>() const
{
if (isNull())
return 0;
return std::stoi(result_.getValue(row_, column_));
}
template <>
inline long Field::as<long>() const
{
if (isNull())
return 0;
return std::stol(result_.getValue(row_, column_));
}
template <>
inline int8_t Field::as<int8_t>() const
{
if (isNull())
return 0;
return static_cast<int8_t>(atoi(result_.getValue(row_, column_)));
}
template <>
inline long long Field::as<long long>() const
{
if (isNull())
return 0;
return atoll(result_.getValue(row_, column_));
}
template <>
inline unsigned int Field::as<unsigned int>() const
{
if (isNull())
return 0;
return static_cast<unsigned int>(
std::stoi(result_.getValue(row_, column_)));
}
template <>
inline unsigned long Field::as<unsigned long>() const
{
if (isNull())
return 0;
return std::stoul(result_.getValue(row_, column_));
}
template <>
inline uint8_t Field::as<uint8_t>() const
{
if (isNull())
return 0;
return static_cast<uint8_t>(atoi(result_.getValue(row_, column_)));
}
template <>
inline unsigned long long Field::as<unsigned long long>() const
{
if (isNull())
return 0;
return std::stoull(result_.getValue(row_, column_));
}
// std::vector<int32_t> Field::as<std::vector<int32_t>>() const;
// template <>
// std::vector<int64_t> Field::as<std::vector<int64_t>>() const;
} // namespace orm
} // namespace drogon