1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/*
* Utility functions
*
* (c) 2015 Schrodinger, Inc.
*/
#pragma once
#include <algorithm>
#include <array>
#include <string>
#include <vector>
#include <string.h>
#include <sstream>
#include "pymol/type_traits.h"
#include "pymol/zstring_view.h"
std::vector<std::string> strsplit(const std::string &s, char delim=0);
bool cstrlessnat(const char * a, const char * b);
bool strlessnat(const std::string& a, const std::string& b);
/**
* C string comparison class
*/
struct cstrless_t {
bool operator()(const char * a, const char * b) const {
return strcmp(a, b) < 0;
}
};
bool p_strstartswith(const char * s, const char * prefix);
bool p_strcasestartswith(const char * s, const char * prefix);
namespace pymol
{
namespace join_to_string_detail
{
inline void join_to_string_impl(std::ostringstream&){};
template <typename T, typename... OtherTs>
void join_to_string_impl(std::ostringstream& stream, T&& t, OtherTs&&... ts)
{
stream << std::forward<T>(t);
join_to_string_impl(stream, std::forward<OtherTs>(ts)...);
}
} // namespace join_to_string_detail
/**
* Joins data into std::string.
* @param ts printable types to be joined into a string
* @return joined string
* Note: Types must be supported be std::ostringstream::operator<<
*/
template <typename... PrintableTs>
std::string join_to_string(PrintableTs&&... ts)
{
std::ostringstream stream;
join_to_string_detail::join_to_string_impl(
stream, std::forward<PrintableTs>(ts)...);
return stream.str();
}
namespace string_format_detail
{
template <typename T> const T& fwdArgs(const T& t)
{
#if defined(__clang__) || !defined(__GNUC__) || __GNUC__ >= 5
// Not available in GCC 4.8
static_assert(std::is_trivially_copyable<T>::value, "");
#endif
return t;
}
inline const char* fwdArgs(const std::string& t)
{
return t.c_str();
}
inline const char* fwdArgs(const pymol::zstring_view& t)
{
return t.c_str();
}
template <typename... FmtArgs>
std::string string_format_impl(const char* const fmt, FmtArgs&&... fmtargs)
{
auto size = snprintf(nullptr, 0, fmt, fmtargs...);
std::string tmp(size, ' ');
snprintf(&tmp[0], size + 1, fmt, fmtargs...);
return tmp;
}
} // namespace string_format_detail
/**
* C++ version of sprintf
* @param fmt formatting string
* @param fmtargs formatting string arguments
* @return result as std::string
*
* Note: For std::string arguments, the underlying null-terminated string will
* be used.
*/
template <std::size_t N, typename... FmtArgs>
std::string string_format(const char (&fmt)[N], FmtArgs&&... fmtargs)
{
static_assert(N > 1, "Format string must not be empty");
return string_format_detail::string_format_impl(
fmt, string_format_detail::fwdArgs(std::forward<FmtArgs>(fmtargs))...);
}
/**
* C++20's std::string::start_with
* @param str string whose contents will be checked
* @param pre candidate prefix string
* @return true if str begins with pre
*
*/
inline bool starts_with(pymol::zstring_view str, pymol::zstring_view pre)
{
return str.starts_with(pre);
}
double pretty_f2d(float v);
/**
* Compares two strings with consideration of case sensitivity
* @param str1 first string
* @param str2 second string
* @param case_insensitive determines whether the comparison should not consider
* case
*/
bool string_equal_case(pymol::zstring_view str1, pymol::zstring_view str2,
bool case_insensitive = true);
template <typename T> struct cache_value {
using value_type = T;
value_type value = value_type{};
cache_value() = default;
cache_value(T t)
: value(std::move(t))
{
}
cache_value(const cache_value&) {}
cache_value& operator=(const cache_value&) { return *this; }
cache_value(cache_value&& other)
{
std::swap(value, other.value);
}
cache_value& operator=(cache_value&& other)
{
std::swap(value, other.value);
return *this;
}
operator T&() { return value; }
};
template <typename T, std::size_t N>
using cache_array = std::array<cache_value<T>, N>;
} // namespace pymol
|