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
|
/*
* Utility functions
*
* (c) 2015 Schrodinger, Inc.
*/
#include <cstdio>
#include <cctype>
#include <cmath>
#include <sstream>
#include <string>
#include <vector>
#include "Util2.h"
#include "pymol/algorithm.h"
/**
* strsplit: split string `s` by character `delim`
*
* If `delim` is null, then do whitespace split.
*/
std::vector<std::string> strsplit(const std::string &s, char delim) {
std::vector<std::string> elems;
std::istringstream iss(s);
std::string item;
if (delim) {
// token split
while (std::getline(iss, item, delim))
elems.push_back(item);
} else {
// whitespace split
while (iss >> item)
elems.push_back(item);
}
return elems;
}
/**
* Natural string compare: F1 < F2 < F10
*
* Return true if a < b
*/
bool cstrlessnat(const char * a, const char * b) {
if (!b[0])
return false;
if (!a[0])
return true;
bool a_digit = isdigit(a[0]);
bool b_digit = isdigit(b[0]);
if (a_digit && !b_digit)
return true;
if (!a_digit && b_digit)
return false;
if (!a_digit && !b_digit) {
if (a[0] != b[0])
return (a[0] < b[0]);
return cstrlessnat(a + 1, b + 1);
}
int ia, ib, na, nb;
sscanf(a, "%d%n", &ia, &na);
sscanf(b, "%d%n", &ib, &nb);
if (ia != ib)
return ia < ib;
return cstrlessnat(a + na, b + nb);
}
/**
* Natural string compare: F1 < F2 < F10
*/
bool strlessnat(const std::string& a, const std::string& b) {
return cstrlessnat(a.c_str(), b.c_str());
}
/**
* Return true if s starts with the specified prefix, false otherwise.
*/
bool p_strstartswith(const char * s, const char * prefix) {
while (*prefix)
if (*s++ != *prefix++)
return false;
return true;
}
/**
* case-insensitive version of p_strstartswith
*/
bool p_strcasestartswith(const char * s, const char * prefix) {
for (; *prefix; ++s, ++prefix)
if (*s != *prefix && tolower(*s) != tolower(*prefix))
return false;
return true;
}
namespace pymol
{
/**
* Convert float to double, rounded to decimal precision.
*/
double pretty_f2d(float f)
{
if (f == 0.0f) {
// don't call log10(0.0)
return 0.0;
}
int digits = std::ceil(std::log10(std::fabs(f)));
auto factor = std::pow(10.0L, 7 - digits);
return std::round(f * factor) / factor;
}
bool string_equal_case(
pymol::zstring_view str1, pymol::zstring_view str2, bool case_insensitive)
{
return pymol::ranges::equal(str1, str2,
[case_insensitive](char c1, char c2) {
return case_insensitive ? std::tolower(c1) == std::tolower(c2)
: c1 == c2;
});
}
} // namespace pymol
|